我有一个带有登录屏幕的 java swing 应用程序。登录屏幕有一个提交按钮,用于在输入用户凭据后按下。当按下按钮时,等待光标会使用其玻璃窗格在窗口上方抛出。还有一个默认的鼠标适配器,它对任何鼠标操作都不做任何事情。
private final static MouseAdapter mouseAdapter =
new MouseAdapter() {};
/** Sets cursor for specified component to Wait cursor */
public static void startWaitCursor(JComponent component) {
log.debug("startWaitCursor()");
RootPaneContainer root =
((RootPaneContainer) component.getTopLevelAncestor());
Component glass = root.getGlassPane();
glass.setCursor(WAIT_CURSOR);
glass.addMouseListener(mouseAdapter);
glass.setVisible(true);
//force repaint of glass pane in 20ms for more responsive GUI
glass.repaint(20);
}
public static void stopWaitCursor(JComponent component) {
log.debug("stopWaitCursor()");
RootPaneContainer root =
((RootPaneContainer) component.getTopLevelAncestor());
Component glass = root.getGlassPane();
glass.setCursor(DEFAULT_CURSOR);
glass.removeMouseListener(mouseAdapter);
//force repaint of glass pane in 20ms for more responsive GUI
glass.repaint(20);
glass.setVisible(false);
}
我曾假设此设置可以在后端方法发生时保护我免受多次点击/按键。我发现事实并非如此。所以在 ButtonListener.actionPerformed 中,我放了一些如下逻辑:
static boolean waiting = false;
class ButtonListener implements ActionListener {
ButtonListener() {
super();
}
public void actionPerformed(ActionEvent e) {
log.info("LoginWindow.ButtonListener.actionPerformed()");
LoginWindow.this.repaint(50);
if (!waiting) {
try {
waiting = true;
verifyLogin();
} finally {
waiting = false;
}
}
}
}
我发现这可以保护我免受按键的影响,但不能防止鼠标点击!如果我在执行 verifyLogin() 时反复按下提交按钮,鼠标点击似乎被缓存在某处,并且在验证登录完成后,每次鼠标点击都会被处理!
我对这里发生的事情感到非常困惑。有人有想法吗?
更新:
嗯,通过遵循 Cyrille Ka 建议的方法:即在单独的线程中执行 verifyLogin() 方法并禁用按钮,我现在在多次鼠标单击后只得到两个事件,但第二个事件仍然很烦人。
代码现在是:
public void actionPerformed(ActionEvent e) {
loginButton.setEnabled(false);
log.infof("LoginWindow.ButtonListener.actionPerformed(). Event occurred at %1$tb %1$te %1$tY %1$tT.%1$tL",
new Date(e.getWhen()));
LoginWindow.this.repaint(50);
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
verifyLogin();
loginButton.setEnabled(true);
}});
}
但是第二个事件仍然进入。我的日志显示第二个事件发生在第一个事件之后大约 280 毫秒,但直到 4 秒后才执行,尽管 setEnabled() 是 actionPerformed( ) 事件发生了。
2013-11-13 10:33:57,186 [AWT-EventQueue-0] 信息 carcgLoginWindow - LoginWindow.ButtonListener.actionPerformed()。事件发生在 2013 年 11 月 13 日 10:33:57.175 2013-11-13 10:34:01,188 [AWT-EventQueue-0] 信息 carscgLoginWindow - LoginWindow.ButtonListener.actionPerformed()。事件发生在 2013 年 11 月 13 日 10:33:57.453
我想我可以做一个黑客攻击并丢弃第二个旧的事件或其他东西,但这感觉很难看。这应该不是那么难,我一直在想。
更新 2:来自 JComponent.java 对 setEnabled() 的评论
* <p>Note: Disabling a lightweight component does not prevent it from * receiving MouseEvents.
由于所有的 Swing 组件都是轻量级的,并且 setEnabled 不会阻止组件接收鼠标事件,那么是什么阻止了这一点呢?