Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从控制器方法更新面板_Java_Swing_Jpanel - Fatal编程技术网

Java 从控制器方法更新面板

Java 从控制器方法更新面板,java,swing,jpanel,Java,Swing,Jpanel,我想从我的控制器更新主框架(类GUI)上的面板。基本上,每个模拟步骤都应该更新面板 for (int step = 0; step < simSteps; step++){ this.gui.updateGUI(this.stats, step); } 我的BarPanel类覆盖了paintComponent方法,在这里我只使用一个图形对象来绘制一些东西。 启动模拟时,面板仅在最后一个模拟步骤后更新,尽管我已经知道在每个模拟步骤中都会调用updateGU

我想从我的控制器更新主框架(类GUI)上的面板。基本上,每个模拟步骤都应该更新面板

    for (int step = 0; step < simSteps; step++){
         this.gui.updateGUI(this.stats, step);
    }
我的BarPanel类覆盖了paintComponent方法,在这里我只使用一个图形对象来绘制一些东西。 启动模拟时,面板仅在最后一个模拟步骤后更新,尽管我已经知道在每个模拟步骤中都会调用updateGUI()方法(我做了一些调试输出)


有人知道为什么会这样吗

如果您非常快地更新GUI,您将看不到中间的更改,因此在循环中的每个步骤之间添加一些暂停,如:

new Thread() {
  public void run() {
    for (int step = 0; step < simSteps; step++){
      this.gui.updateGUI(this.stats, step);
      try {
        Thread.currentThread().sleep(1000); // wait 1s before each step
      } catch (InterruptedException e) {
        e.printStackTrace();
      }       
    }
  } 
}.start();   


 public void updateGUI(final Stats stats, final int step){
   // the declaration of stats in this class should be marked as volatile like: 
   // private volatile Stats;
   this.stats = stats;
   EventQueue.invokeLater(new Runnable() {
     @Override
     public void run() {
       getContentPane().remove(pollutionPanel);
       pollutionPanel = new BarPanel(settings, stats, possibleColors);
       getContentPane().add(pollutionPanel);
       validate();
       repaint();
     }
   });
 }
新线程(){
公开募捐{
对于(int step=0;step

还要记住,上面的循环不应该由
EventThread
运行,因此您不应该直接在
ActionListener
中运行此代码(例如,在按下
JButton
之后),而应该在
ActionListener.actionPerformed()
创建
新线程中运行此代码,该线程包含
run()中的上述代码
方法,然后使用
yourThread.start()启动此类线程。您也可以使用其他方式在单独的线程中运行它,但这是一个太宽泛的主题,不适合您的问题范围。

如果您很快更新GUI,您看不到中间的更改,因此在循环中的每个步骤之间添加一些暂停,如:

new Thread() {
  public void run() {
    for (int step = 0; step < simSteps; step++){
      this.gui.updateGUI(this.stats, step);
      try {
        Thread.currentThread().sleep(1000); // wait 1s before each step
      } catch (InterruptedException e) {
        e.printStackTrace();
      }       
    }
  } 
}.start();   


 public void updateGUI(final Stats stats, final int step){
   // the declaration of stats in this class should be marked as volatile like: 
   // private volatile Stats;
   this.stats = stats;
   EventQueue.invokeLater(new Runnable() {
     @Override
     public void run() {
       getContentPane().remove(pollutionPanel);
       pollutionPanel = new BarPanel(settings, stats, possibleColors);
       getContentPane().add(pollutionPanel);
       validate();
       repaint();
     }
   });
 }
新线程(){
公开募捐{
对于(int step=0;step

还要记住,上面的循环不应该由
EventThread
运行,因此您不应该直接在
ActionListener
中运行此代码(例如,在按下
JButton
之后),而应该在
ActionListener.actionPerformed()
创建
新线程中运行此代码,该线程包含
run()中的上述代码
方法,然后使用
yourThread.start()启动此类线程。您也可以使用其他方式在单独的线程中运行它,但这是一个太宽泛的主题,不适合您的问题范围。

所以,基本概念是,您希望生成一些动画,用户界面会在一段时间内更新这些动画。这不是一个罕见的请求,有很多例子

要记住的事情:

  • Swing是单线程的
  • 不要做任何可能会阻止事件调度线程的事情,这将阻止用户界面被更新,直到控件被传递回它为止
  • 不要从EDT上下文之外更新UI
好吧,这听起来有点矛盾,但是Swing提供了一些工具让你的生活更轻松

你可以

使用
SwingWorker
您将根据问题的复杂程度使用哪种方法,
SwingWorker
使用自己的
Thread
调用
doInBackground
,允许您处理耗时的任务,但提供安全更新UI的能力


定时器
在EDT上下文中触发其更新,使其保存以更新UI,但不执行

中耗时的任务。因此,基本概念是,您希望生成一些动画,其中UI会在一段时间内更新。这不是一个罕见的请求,有很多例子

要记住的事情:

  • Swing是单线程的
  • 不要做任何可能会阻止事件调度线程的事情,这将阻止用户界面被更新,直到控件被传递回它为止
  • 不要从EDT上下文之外更新UI
好吧,这听起来有点矛盾,但是Swing提供了一些工具让你的生活更轻松

你可以

使用
SwingWorker
您将根据问题的复杂程度使用哪种方法,
SwingWorker
使用自己的
Thread
调用
doInBackground
,允许您处理耗时的任务,但提供安全更新UI的能力


Timer
在EDT上下文中触发其更新,使其保存以从更新UI,但不执行耗时的任务。请提供一个可运行的示例,使用
SwingWorker
或Swing
计时器
在更新之间注入某种延迟欢迎来到这里。请以使用
SwingWorker
或Swingimport java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingWorker; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Test { public static void main(String[] args) { new Test(); } public Test() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.setSize(400, 400); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public interface StepContainer { public void addStep(int index); } public class TestPane extends JPanel implements StepContainer { private int step = 0; public TestPane() { setLayout(new GridBagLayout()); PopulateWorker worker = new PopulateWorker(10, this); worker.execute(); } @Override public void addStep(int step) { JButton btn = new JButton(Integer.toString(step)); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; add(btn, gbc); revalidate(); repaint(); } } public class PopulateWorker extends SwingWorker<Void, Integer> { private int steps; private StepContainer parent; public PopulateWorker(int steps, StepContainer parent) { this.steps = steps; this.parent = parent; } @Override protected Void doInBackground() throws Exception { Thread.sleep(1000); for (int index = 0; index < steps; index++) { publish(index); Thread.sleep(1000); } return null; } @Override protected void process(List<Integer> chunks) { for (int step : chunks) { parent.addStep(step); } } } }
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.setSize(400, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface StepContainer {

        public void addStep(int index);
    }

    public class TestPane extends JPanel implements StepContainer {

        private int step = 0;

        public TestPane() {
            setLayout(new GridBagLayout());
            Timer timer = new Timer(1000, new PopulateAction(10, this));
            timer.start();
        }

        @Override
        public void addStep(int step) {
            JButton btn = new JButton(Integer.toString(step));
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(btn, gbc);
            revalidate();
            repaint();
        }

    }

    public class PopulateAction implements ActionListener {

        private int steps;
        private StepContainer parent;
        private int step;

        public PopulateAction(int steps, StepContainer parent) {
            this.steps = steps;
            this.parent = parent;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            parent.addStep(step);
            if (step == steps - 1) {
                ((Timer) e.getSource()).stop();
                step = 0;
            }
            step++;
        }
    }
}