【问题标题】:Painting from listener [closed]听众的绘画[关闭]
【发布时间】:2012-09-29 17:06:32
【问题描述】:

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

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

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

【问题讨论】:

  • 在 EDT 中调用侦听器。只是repaint() 安排一个绘制操作。见docs.oracle.com/javase/6/docs/api/javax/swing/…
  • 因放弃正确的解决方案而被否决。抱歉,SwingWorker 不仅是一个选项,它实际上是您的 最佳 选项。侦听器的复杂性与此无关,只是可能会建议您重构代码,这样您就不必忽略 SwingWorker 的使用。
  • 删除了反对票,但同样,如果您要避免最佳解决方案,我建议您告诉我们更多原因。
  • @MadP:在查看他过去的帖子时,我敢打赌他说的是"Due to complexity of the listener, SwingWorker is NOT an option...",因为他根本不了解如何使用 SwingWorker,但我也打赌我们永远不会知道是因为他似乎已经放弃了这个问题并转到the next
  • @HovercraftFullOfEels 这似乎是一个“压倒性证据反对 - 忽略”的案例......

标签: java swing user-interface


【解决方案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);

        }
    });

}

气垫船积分有效。任何耗时的任务都应在 EDT 之外的后台执行。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多