【问题标题】:Why doesn't my JPanel update while running simulation?为什么我的 JPanel 在运行模拟时不更新?
【发布时间】:2013-12-27 00:33:16
【问题描述】:

当我在 JPanel 中运行移动正方形的模拟时,GUI 没有更新。在整个模拟完成之前,它不会刷新 JPanel。

我的代码:

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI(); 
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    } 
}

class MyPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private int squareX = 50;
    private int squareY = 50;
    private int squareW = 20;
    private int squareH = 20;

    public MyPanel() {

        setBorder(BorderFactory.createLineBorder(Color.black));

        doAnimation();

    }

    private void doAnimation(){
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                for(int x = 0; x < 250-squareW; x+=squareX){
                    for(int y = 0; y < 200-squareH; y+=squareY){
                        moveSquare(x,y);
                    }
                }
            }
        });
    }

    private void moveSquare(int x, int y) {
        int OFFSET = 1;
        if ((squareX!=x) || (squareY!=y)) {
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
            squareX=x;
            squareY=y;
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        } 
    }


    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);       
        g.drawString("This is my custom Panel!",10,20);
        g.setColor(Color.RED);
        g.fillRect(squareX,squareY,squareW,squareH);
        g.setColor(Color.BLACK);
        g.drawRect(squareX,squareY,squareW,squareH);
    }  
}

【问题讨论】:

  • 如果在每个moveSquare(x,y); 之后执行Thread.sleep(100); 是否有效?
  • 不要阻塞 EDT(事件调度线程)——当这种情况发生时,GUI 将“冻结”。而不是调用Thread.sleep(n) 实现一个Swing Timer 用于重复任务或SwingWorker 用于长时间运行的任务。有关详细信息,请参阅Concurrency in Swing
  • 不,它没有......已经用 Thread.sleep(1000); 尝试过
  • @AndrewThompson,有些人会争辩说等待不是阻塞,即使你提出了一个有效的观点,也会给你持续的反对票。 Don't believe me? see here

标签: java swing user-interface jpanel simulation


【解决方案1】:

看这里..

private void moveSquare(int x, int y) {
    int OFFSET = 1;
    if ((squareX!=x) || (squareY!=y)) {
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        squareX=x;  // It makes squareX will be 0 in first iteration
        squareY=y;  // It makes squareY will be 0 in first iteration
        repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
    } 
}

最后你得到了无限循环。所以改变它..

【讨论】:

  • 我没有看到无限循环,具体在哪里?
【解决方案2】:

直到整个模拟完成后才会刷新 JPanel 完成。

是的。更新将执行一次。因为您在 invokeLater 的 Runnable 中运行以下代码,该代码通过包装为单个事件提交给 EDT:

SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                for(int x = 0; x < 250-squareW; x+=squareX){
                    for(int y = 0; y < 200-squareH; y+=squareY){
                        moveSquare(x,y);
                    }
                }
            }
        });

您在moveSquare(x, y) 方法中发出的所有重绘请求都被包装在该单个事件中。即使我们在同一个事件处理程序中连续多次调用重绘,Swing 也足够聪明,可以在一次绘制操作中获取这些信息并重绘屏幕的这些部分。换句话说,Swing 不会连续多次重新绘制组件,即使代码看起来是这样做的。查看this official tutorial page获取详细解释和示例。

但是,像这样运行一个长循环会使您的 GUI 应用程序无响应:因为它可能正在等待 EDT。并利用Swing Timer类的周期性任务来制作动画效果。

【讨论】:

  • 我到底应该把计时器放在哪里?我不明白。
  • 我从该教程页面中获取了代码并对其进行了修改以执行自动动画,而不必手动拖放。但它冻结了。我的意思是这是我上面问题中的原始代码......这就是我在发布这个问题之前所做的事情。
  • @BrianTHannan,如果你还没用过,你是不会理解的。请浏览链接页面并品尝演示并尝试使用它。
  • 没有自动动画的演示。链接?
  • 没关系,在这里找到一个例子:stackoverflow.com/questions/16316132/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 2017-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多