0

这是我的问题的简单版本。我有 3 个类: 公共类 TopographyFrame 扩展 JFrame - 带有 JPAnel 和按钮的简单 JFrame 公共类 TopograpyPanel 扩展 JPanel - JPanel 以填充矩形 公共类 Siec - 执行计算并在 JAnale 上调用重绘的类

在 JPanel 我重写了 paintComponent() 方法

public void paintComponent (Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        System.out.println(rectangles.length);
        for(int i = 0 ; i < rectangles.length ; i++){
            g2.setPaint(neurony[i].winner);
            g2.fillRect((int)rectangles[i].x,(int)rectangles[i].y,(int)rectangles[i].width, (int)rectangles[i].height);
        }
    }

神经元 - 具有公共颜色获胜者字段的对象数组

在 Siec 类中,我参考了 JPanel 以在 JFrame 类中重新绘制它,我有一个带有私有操作侦听器的按钮:

class MyListener implements ActionListener{
        Siec s;
        public MyListener(Siec s){
            this.s = s;
        }
        public void actionPerformed(ActionEvent arg0) {
            try {
                s.forPaint();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Siec 中的 forPaint() 方法如下所示:

public void forPaint(){

        setTopography();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        setTopography();
    }
public void setTopography() {
    for (int i = 0; i < vector.colors.length; i++) {
            neurony[i].winner = vector.colors[(int)(random() * 900 % vector.colors.length)];
    }
    panel.repaint();
}

vector.color 是颜色数组

所以我的问题是:当我单击一个按钮时,我想立即重新绘制 JPanel,然后在 3 秒后重新绘制一次。Insted JPanel 在 3 秒延迟后仅重绘一次。}

4

3 回答 3

2

您永远不能在事件处理线程上休眠、等待或以其他方式暂停。这样做会阻止处理所有事件,包括绘画事件。您的第一幅绘画无法发生,因为您正在事件线程上睡觉,从而阻止它发生。

做任何类型的动画——即使是像这样简单的东西——的正确方法是创建自己的线程。第二个线程可以调用 repaint(),休眠 3 秒,然后再次调用 repaint()。SwingWorker类名义上是一种更简单的方法,但老实说,初学者总是发现创建自己的线程更容易。

于 2012-04-30T20:31:07.430 回答
1

您正在调度 UI 线程上的重绘,然后休眠(阻塞)UI 线程 3 秒,然后再次请求另一个重绘。这两个要么在此方法完成后(3 秒后)彼此非常接近,要么合并为一个更新(之后也是如此)。而不是sleep(3000)然后setTopography再次调用您,您可以安排setTopography在 UI 线程上的调用在 3 秒后发生。

例如,看看 Swing Timer:http: //docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

所以类似于:

javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        setTopography();
    }
});
timer.setRepeats(false);
timer.start();
于 2012-04-30T20:38:20.810 回答
0

由于您的睡眠是在Event Dispatch Thread上执行的,因此在等待结束之前无法执行 repaint() 事件。改为这样做:

private Timer timer = new Timer(); // use java.util.Timer

public void forPaint() {

    setTopography();

    timer.schedule(new TimerTask() {

        @Override
        public void run() {
            setTopography();
        }

    }, 3000);

}

public void setTopography() {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {

            for (int i = 0; i < vector.colors.length; i++) {
                neurony[i].winner = vector.colors[(int)(random() * 900 % vector.colors.length)];
            }
            panel.repaint();
        }
    });
}

请记住,对 Swing 组件(例如您的 JPanel)的所有修改都必须在 EDT 上进行。

于 2012-04-30T20:43:40.213 回答