从听众绘画

时间:2012-09-29 17:06:32

标签: java swing user-interface

我有一个有点复杂的组件监听器。它有很多计算依赖于GUI的当前状态(组件高度,具体而言)。

据我所知,侦听器是在与EDT分开的线程中执行的,它负责处理GUI,因此只有在侦听器执行了代码之后才会执行重绘和验证方法。有没有办法从侦听器线程重新绘制immedatley?

由于监听器的复杂性,SwingWorker不是一个选项......

1 个答案:

答案 0 :(得分:1)

我认为你的理解是有缺陷的。系统触发的所有事件都从它们被触发的线程中调度。也就是说,如果您从另一个线程手动调用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);

        }
    });

}

Hovercrafts点有效。任何耗时的任务都应该在EDT的后台执行。

您应该在适当的时候使用SwingUtilities.invokeLater / invokeAndWait与EDT重新同步。