我有一个处理日期和时间的Swing应用程序,所以很多测试都在改变系统的日期和时间设置。 在测试期间,我们注意到在减少时钟后,应用程序将忽略第一次单击。
是Swing / Java / Windows的错误吗?有解决方法吗?
有趣的是,只有在减少日期/时间设置时才会出现此问题。如果我增加它,应用程序就会正常运行。
情况:
代码示例(您可以使用它来证明情况):
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);
}
});
}
}
答案 0 :(得分:1)
如所见here,Swing使用日期来检查事件何时发生。因此,在某种程度上,通过放弃您的操作,处理程序在此处起作用,因为它发生在“最后一个操作之前”。我无法确认你这一点,但是有些布局管理器或其他处理程序在这里搞乱了一些东西,以防止延迟事件搞乱当前流程。
答案 1 :(得分:0)
我已经通过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.BasicButtonListener
。
Button
类确实有setMultiClickThreshhold
,但如果阈值小于IllegalArgumentException
,它会抛出0
。
所以,作为一种解决方法,我这样做了:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.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);
}
});
}
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);
}
}