Swing在减lessWindows时间后忽略第一次点击

我有一个Swing应用程序处理date和时间,所以很多testing都是在更改系统的date和时间设置。 在testing过程中,我们注意到在减less时钟之后,应用程序忽略了第一次点击。

是Swing / Java / Windows的错误吗? 有没有解决这个问题的方法?

有趣的是,这个问题只发生在减lessdate/时间设置。 如果我增加它,应用程序的行为正常。

情况:

  • Swing应用程序运行。
  • 减lessWindowsdate和时间设置(例如,从15:00更改时间到14:00)。
  • 请注意,Swing应用程序中的第一次单击不会触发任何操作。

代码示例(可以用它来certificate情况):

import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JFrame; public class Main { public static void main(String[] args) { final JFrame frame = new JFrame("frame"); final JButton button = new JButton("button"); button.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { System.out.println("Button Pressed!"); } }); frame.add(button); frame.setSize(200, 200); frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(final WindowEvent e) { System.exit(0); } }); } } 

如此处所示,Swing使用日期来检查事件何时发生。 所以,在某种程度上,一个处理程序正在这里行动,通过放弃你的行动,因为它发生在最后一个行动“之前”。 我不能确认你,但是有些布局管理器或者其他的处理器在这里弄乱了某些东西,以防止延迟的事件搞乱当前的流程。

我已经通过Eclipse对它进行了调试,并发现了正在发生的事情。

  • 时钟在15:00。
  • 点击按钮。 摇摆记录上次活动的时间到15:00。
  • 将时钟更改为14:00h。
  • 点击按钮。 Swing忽略事件,因为它看起来像一个多点击。

这里的问题是Swing检查多点击所做的比较是这样的:

 if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) { shouldDiscardRelease = true; 

在这里, currentTime - lastTime产生一个负值。 它小于0 (我的multiClickThreshhold ),所以它不会触发操作事件:

 public void mouseReleased(MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e)) { // Support for multiClickThreshhold if (shouldDiscardRelease) { shouldDiscardRelease = false; return; } AbstractButton b = (AbstractButton) e.getSource(); ButtonModel model = b.getModel(); model.setPressed(false); model.setArmed(false); } } 

上面列出的所有源都在javax.swing.plaf.basic.BasicButtonlistner

Button类有一个setMultiClickThreshhold ,但是当阈值小于0 ,它会抛出IllegalArgumentException异常。

所以,作为一种解决方法,我这样做了:

 import java.awt.event.ActionEvent; import java.awt.event.Actionlistner; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.reflect.Field; import javax.swing.AbstractButton; import javax.swing.JButton; import javax.swing.JFrame; public class Main { public static void main(String[] args) throws Exception { final JFrame frame = new JFrame("frame"); final JButton button = new JButton("button"); removeMulticlickThreshold(button); button.addActionlistner(new Actionlistner() { public void actionPerformed(final ActionEvent e) { System.out.println("Button Pressed!"); } }); frame.add(button); frame.setSize(200, 200); frame.setVisible(true); frame.addWindowlistner(new WindowAdapter() { @Override public void windowClosing(final WindowEvent e) { System.exit(0); } }); } private static void removeMulticlickThreshold(final JButton button) throws Exception { final Field multiClickThreshhold = AbstractButton.class.getDeclaredField("multiClickThreshhold"); multiClickThreshhold.setAccessible(true); multiClickThreshhold.set(button, Long.MIN_VALUE); } }