我有一个Swing应用程序处理date和时间,所以很多testing都是在更改系统的date和时间设置。 在testing过程中,我们注意到在减less时钟之后,应用程序忽略了第一次点击。
是Swing / Java / Windows的错误吗? 有没有解决这个问题的方法?
有趣的是,这个问题只发生在减lessdate/时间设置。 如果我增加它,应用程序的行为正常。
情况:
代码示例(可以用它来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对它进行了调试,并发现了正在发生的事情。
这里的问题是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); } }