【问题标题】:Postpone Event Queue after Focus Lost焦点丢失后推迟事件队列
【发布时间】:2012-03-05 18:19:19
【问题描述】:

我有一个带有自定义单元格编辑器的JTable。编辑器实现了FocusListener,因此如果用户点击离开单元格,我可以检查单元格的内容是否有效。

我想在focusLost(在EventDispatchThread)中使用JOptionPane,以允许用户选择是恢复为旧值还是接受调整后的值。

这就是问题所在;如果用户正在编辑单元格,然后单击远离表格的按钮,按钮的actionlisteners 会在JOptionPane 返回之前收到警报。

这就是我想要发生的事情:

  • 用户编辑单元格
  • 用户点击按钮
  • 单元格检测到焦点丢失
  • 显示 JOptionPane 并且用户选择操作
  • JOptionPane 关闭并设置单元格的值
  • Button 的 actionListener 被调用

相反,这正在发生:

  • 用户编辑单元格
  • 用户点击按钮
  • 单元格检测到焦点丢失
  • 显示 JOptionPane 并且用户选择操作
  • Button 的 actionListener 被调用
  • JOptionPane 关闭并设置单元格的值

是否可以将按钮的操作事件推迟到JOptionPane 关闭之后?

从其他线程中,我了解到JDialog 做了一些魔术来确保事件调度继续进行,因此 Dialog 本身可以处理事件。

【问题讨论】:

  • 是的,JDialog 有一些魔力,因为当您从 AWT 事件队列中显示 JDialog 时,您实际上是在阻止新事件被分派,因为对 JDialog 上的 setVisible(true) 的调用是阻塞的。为了避免这种情况,JDialog 访问事件队列并自动调度新的传入事件。如果你想在当前处理的事件之后推迟一个事件,你可以使用SwingUtilities.invokeLater(Runnable)。 Runnable 在当前事件结束后执行。
  • 无论你做什么,都不要使用 focusListener - 特别是在表格(或树或组合)编辑的上下文中,它的级别太低且极难正确(记住:焦点处理是高度依赖操作系统,什么时候发生的顺序是不可预测的,加上表本身会干扰内部魔法)去做别的事情......

标签: java swing focus joptionpane event-dispatch-thread


【解决方案1】:

将您的验证逻辑放入TableCellEditor#stopCellEditing(),显示您的对话框并在值无效时返回 false。

要在失去焦点时自动停止表格编辑,请使用table.putClientProperty("terminateEditOnFocusLost", true);,但我认为这不会阻止按钮操作侦听器运行。相反,我通常会在 actionPerformed 中停止表格编辑,并且在返回 false 时不执行任何操作(或者在适当的时候取消编辑,例如,如果操作是删除该表格行)。

【讨论】:

  • 谢谢,但这并不是我真正想要的。验证工作正常。
  • @user1208882 验证工作正常 我不同意:验证本身(确定给定输入是否有效)可能正在工作,整个过程,包括用户交互并防止触发动作,不是。
【解决方案2】:

据我所知,在用户从 JOptionPane 中选择正确值之前,您根本不希望按钮的动作侦听器激活。

在我看来,解决方案似乎是设置一个“禁用”标志,一旦触发 focusLost,该标志就会上升。一旦做出选择,禁用标志就会下降。当按钮动作被触发时,它会检查表单是否被禁用;如果是,它什么也不做。如果不是,它会照常继续。

请注意,一旦用户在 JOptionPane 中选择了某些内容,按钮事件将不会自动进行,而是必须再次单击该按钮。对我来说,这似乎是更好的功能,然后在他需要更改表单后再次为他“单击”按钮。

【讨论】:

  • 是的,这确实很有意义,但是,我想不出整洁的方法来实现它。还有许多其他 GUI 组件需要注意“禁用”标志。
猜你喜欢
  • 2018-03-15
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 2015-06-17
相关资源
最近更新 更多