【问题标题】:multiple dispatchEvent calls on a JButtonJButton 上的多个 dispatchEvent 调用
【发布时间】:2015-07-16 08:17:49
【问题描述】:

我在 Java Swing 应用程序中有一个定制的 JButton。 它会根据鼠标事件改变它的外观。
MouseEvent.MOUSE_ENTERED - 将触发按钮的悬停图像。 MouseEvent.MOUSE_PRESSED - 将触发按下的图像。
MouseEvent.MOUSE_RELEASED - 将前景变为灰色并禁用按钮。
实际点击鼠标效果很好。

我想添加对按 ENTER 键的支持。
简单地调用button.doClick() 并没有经历悬停-按下-发布周期,而是简单地跳转到发布事件。

所以我有这个简短而有效的代码来做这件事。

InputMap im = workspacePnl.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = workspacePnl.getActionMap();
im.put(KeyStroke.getKeyStroke("ENTER"), "connect");
am.put("connect", new ConectAction());

private class ConectAction extends AbstractAction {
        @Override
        public void actionPerformed(ActionEvent ev) {
            simulateClick();   
}

以及有问题的代码:

public void simulateClick() {
        MouseEvent evt;

        evt = new MouseEvent(connectBtn,
                MouseEvent.MOUSE_ENTERED, 1, 0, 0, 0, 1, false);
        connectBtn.dispatchEvent((AWTEvent) evt);

        //CommonUtil.sleep(300);

         evt = new MouseEvent(connectBtn,
                MouseEvent.MOUSE_PRESSED, 8, 0, 0, 0, 1, false);
        connectBtn.dispatchEvent((AWTEvent) evt);

        //CommonUtil.sleep(300);

        evt = new MouseEvent(connectBtn,
                MouseEvent.MOUSE_RELEASED, 20, 0, 0, 0, 1, false);
        connectBtn.dispatchEvent((AWTEvent) evt);
    }

我试图让 ENTER 按下通过相同的路径:
触发一个 MOUSE_ENTERED 事件,该事件将改变按钮的悬停外观,然后是 MOUSE_PRESSED 和 MOUSE_RELEASED。
但我只看到最后一个事件效果。就好像我只是单独触发最后一个事件,它缺乏交互式软件的活力。 我尝试(可以看出已注释掉)在每次事件触发后让线程进入睡眠状态,但它没有效果。 如果我尝试触发其他两个事件中的每一个,它们本身就会在屏幕上引人注目。是批处理把事情搞砸了。

我怎样才能一个接一个地触发一系列dispatchEvents,这些事件都会被用户注意到?我怎样才能让程序等待当前的 dispatchEvent 工作,然后再大步前进到下一个?

任何帮助或见解将不胜感激。

【问题讨论】:

  • "MouseEvent.MOUSE_ENTERED - 将触发按钮的悬停图像。" - JButton#setRolloverEnabled & JButton#setRolloverIcon
  • "MouseEvent.MOUSE_PRESSED - 将触发按下的图像。" - JButton#setRolloverSelectedIcon &/或JButton#setSelectedIcon
  • public void simulateClick() { ...doClick有什么问题吗?
  • 这并不能解决我的问题。确实,我可以使用这种方法来更好地自定义按钮(也许。我没有尝试过,所以我不知道这是否会引入错误),但我仍然需要在没有帮助的情况下手动调用这些事件物理鼠标,以创建实际按下的错觉。我写了 doClick 什么也没做。
  • 实际上,它在大多数情况下都是如此。根据您的需要,您可能需要在JButtonButtonModel 上使用ChangeListener 来修改“选定图标”,假设您希望在按下[Enter] 按钮时显示“选定图标”。 doClick 对您不起作用的原因是您没有监控按钮模型的更改

标签: java swing mouseevent jbutton dispatchevent


【解决方案1】:

我怎样才能一个接一个地触发一系列 dispatchEvents 被用户注意到了吗?我怎样才能让程序等待当前 dispatchEvent 在进入下一个之前发挥它的魔力?

  • 在 ButtonComponents 中正确实现了鼠标和按键事件,不要使用 MouseListener,使用来自ButtonModel 的事件,通过使用ChangeListener,对于example

【讨论】:

    【解决方案2】:

    MouseEvent.MOUSE_ENTERED - 将触发按钮的悬停图像。

    利用按钮提供的翻转支持,请参阅JButton#setRolloverEnabledJButton#setRolloverIcon

    MouseEvent.MOUSE_PRESSED - 将触发按下的图像。

    有点困难,但您可以使用ButtonModel 的侦听器进行更改并根据您的要求更新图标

    MouseEvent.MOUSE_RELEASED - 将前景变为灰色并禁用按钮。

    应该可以通过使用ActionListener来实现

    我正在尝试让 ENTER 按下相同的路径:

    JButton#doClick会自动遍历模型的isArmedisPressed状态,会触发之前的cmets提供的状态变化...

    用鼠标...

    用键盘...

    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.ImageIcon;
    import javax.swing.InputMap;
    import javax.swing.JButton;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.KeyStroke;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
    
                setLayout(new GridBagLayout());
                JButton btn = new JButton();
                try {
                    btn.setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/Trash01.png"))));
                    btn.setRolloverIcon(new ImageIcon(ImageIO.read(getClass().getResource("/Trash02.png"))));
                    btn.setRolloverEnabled(true);
    //              btn.setSelectedIcon(new ImageIcon(ImageIO.read(getClass().getResource("/Trash03.png"))));
                } catch (IOException ex) {
                    Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
                }
    
                btn.getModel().addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        if (btn.getModel().isPressed()) {
                            try {
                                btn.setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/Trash03.png"))));
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        } else {
                            try {
                                btn.setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/Trash01.png"))));
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
    
                        System.out.println("Armed: " + btn.getModel().isArmed());
                        System.out.println("Enabled: " + btn.getModel().isEnabled());
                        System.out.println("Pressed: " + btn.getModel().isPressed());
                        System.out.println("Rollover: " + btn.getModel().isRollover());
                        System.out.println("Selected: " + btn.getModel().isSelected());
    
                    }
                });
    
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridwidth = GridBagConstraints.REMAINDER;
    
                add(btn, gbc);
                add(new JTextField("Stealer of focus"), gbc);
    
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        btn.setEnabled(false);
                    }
                });
    
                InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = getActionMap();
                im.put(KeyStroke.getKeyStroke("ENTER"), "connect");
                am.put("connect", new AbstractAction() {
    
                    @Override
                    public void actionPerformed(ActionEvent ev) {
                        System.out.println("click");
                        btn.doClick();
                    }
                });
            }
    
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      因为您的整个代码都在 EventDispatchingThread (EDT) 上运行,所以它是一起批处理的。

      当您从 actionPerformed() 调用 simulateClick() 时,在新线程而不是同一线程(将是 EDT)上调用它。

      【讨论】:

      • 是的,让我们违反 Swing 的单线程规则,这永远不会伤害任何人
      猜你喜欢
      • 1970-01-01
      • 2011-08-24
      • 1970-01-01
      • 2013-04-24
      • 2012-11-27
      • 2014-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多