Java 听者画

Java 听者画,java,swing,user-interface,Java,Swing,User Interface,我有一个有点复杂的组件侦听器。它有大量的计算,这取决于GUI的当前状态(具体来说是组件高度) 据我所知,监听器是在一个独立于EDT的线程中执行的,EDT负责GUI,因此只有在监听器执行了它的代码之后,才会执行重绘和验证方法。有没有办法从侦听器线程重新绘制ImmaDatley 由于听众的复杂性,SwingWorker不是一个选项…我认为你的理解有缺陷。系统触发的所有事件都从触发它们的线程中调度。也就是说,如果您从不同的线程手动调用fireXxxEvent,那么它将从该线程上下文通知其侦听器。但是,

我有一个有点复杂的组件侦听器。它有大量的计算,这取决于GUI的当前状态(具体来说是组件高度)

据我所知,监听器是在一个独立于EDT的线程中执行的,EDT负责GUI,因此只有在监听器执行了它的代码之后,才会执行重绘和验证方法。有没有办法从侦听器线程重新绘制ImmaDatley


由于听众的复杂性,SwingWorker不是一个选项…

我认为你的理解有缺陷。系统触发的所有事件都从触发它们的线程中调度。也就是说,如果您从不同的线程手动调用
fireXxxEvent
,那么它将从该线程上下文通知其侦听器。但是,所有系统触发事件(例如鼠标和按键事件)将在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重新同步。

在EDT中调用侦听器。只是
repaint()
安排了一个绘制操作。请参阅投票支持立即放弃正确的解决方案。对不起,SwingWorker不仅是一个选择,事实上它是你最好的选择。监听器的复杂性与此无关,只是建议您重构代码,这样您就不必忽略SwingWorker的使用。投票被否决,但同样,如果您想避免最佳解决方案,我建议您告诉我们更多原因。@MadP:回顾他过去的帖子,我打赌他说的是
“由于听者的复杂性,SwingWorker不是一个选项……”
因为他根本不知道如何使用SwingWorker,但我打赌我们永远也不会知道,因为他似乎已经放弃了这个问题,转而使用它。@HovercraftFullOfEels这似乎是一个“压倒性证据反对-忽略”。。。