为什么我的JPanel在运行模拟时没有更新?

时间:2013-12-09 18:55:54

标签: java swing user-interface jpanel simulation

当我在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);
    }  
}

2 个答案:

答案 0 :(得分:4)

  

在完成整个模拟之前,它不会刷新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应用程序无响应:因为它可能等待E​​DT。并利用Swing Timer类和周期性任务来制作动画效果。

答案 1 :(得分:-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);
    } 
}

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