我有一个有点复杂的组件监听器。它有很多计算取决于 GUI 的当前状态(具体来说是组件高度)。
据我所知,侦听器在与处理 GUI 的 EDT 分开的线程中执行,因此仅在侦听器执行其代码后才执行重绘和验证方法。有没有办法从听众线程中重新绘制 immedatley?
由于侦听器的复杂性,SwingWorker 不是一个选项......
我有一个有点复杂的组件监听器。它有很多计算取决于 GUI 的当前状态(具体来说是组件高度)。
据我所知,侦听器在与处理 GUI 的 EDT 分开的线程中执行,因此仅在侦听器执行其代码后才执行重绘和验证方法。有没有办法从听众线程中重新绘制 immedatley?
由于侦听器的复杂性,SwingWorker 不是一个选项......
我觉得你的理解有问题。系统触发的所有事件都是从触发它们的线程分派的。也就是说,如果您fireXxxEvent
从不同的线程手动调用 THEN,它将从该线程上下文通知它的侦听器。但是,所有系统触发事件(例如鼠标和按键事件)都将在 EDT 内发生。
这是一个简单的测试...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Am I on the EDT = " + EventQueue.isDispatchThread());
}
});
JLabel label = new JLabel("Click me");
label.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Am I on the EDT = " + EventQueue.isDispatchThread());
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
frame.add(label, gbc);
gbc.gridy++;
frame.add(button, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
气垫船积分有效。任何耗时的任务都应在 EDT 的后台执行。
您应该在适当的情况下使用 SwingUtilities.invokeLater/invokeAndWait 与 EDT 重新同步。