【发布时间】:2017-04-17 21:06:37
【问题描述】:
在我为我的类构建的程序中,我有一个扩展 Swing JPanel 并实现 MouseListener 的类,为此我使用两个实例化 - 一个用作 JPanel,另一个用作该 JPanel 的鼠标侦听器.
但是当我在窗口中单击时,repaint() 鼠标侦听器中的 MouseClicked 方法无法调用第一个对象的 paintComponent() 方法。例如:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestPanel extends JPanel implements MouseListener{
static boolean black;
static TestPanel test = new TestPanel();
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseClicked(MouseEvent e){ //Expected behavior: the square turns black immediately
System.out.println("CLICK!");
black = true;
test.repaint(); //this fails
try{
Thread.sleep(3000);
}catch(Exception ex){}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
System.out.println("Painting...");
g2d.setColor(Color.white);
if(black){
g2d.setColor(Color.black);
}
g2d.fillRect(0, 0, 200, 200);
}
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.addMouseListener(new TestPanel());
test.setPreferredSize(new Dimension(200, 200));
frame.add(test);
frame.pack();
frame.setVisible(true);
while (true){
black = false;
test.repaint();
Thread.sleep(100);
}
}
}
如果您观察单击时发生的情况,则在单击注册后屏幕会保持白色 3 秒,直到循环再次启动,即鼠标侦听器中的 repaint() 调用不起作用。为什么会这样?
我猜如果我为对象创建不同的类会起作用,但我很好奇为什么它不能以这种方式起作用。
【问题讨论】:
-
不要阻塞 EDT(事件调度线程)。发生这种情况时,GUI 将“冻结”。有关详细信息和修复,请参阅Concurrency in Swing。如果您想延迟效果,请将其安排在基于
Timer的单次 Swing 上。 -
没有多个线程有没有办法做到这一点?到目前为止,我的程序只使用一个线程。
-
“没有多线程有没有办法做到这一点?” Swing
Timer在 EDT 上运行.. -
这很奇怪,当我在 main 方法中执行完全相同的操作时,它工作正常。我只是在外部方法中遇到了这个问题。
-
这没什么奇怪的——从 main 方法运行的代码没有在 Swing 事件线程上运行。但这不是解决您的问题的安全解决方案,因为这会引入其他间歇性问题的风险,因为您正在从 Swing 事件线程运行一些 Swing 代码。至于
"...isn't really what I had in mind..."——很难猜出你的想法。您引入延迟的主要目的是什么?如果您需要设置延迟,请使用 Swing Timer。如果没有,那你想做什么?