【发布时间】:2020-02-12 10:41:17
【问题描述】:
这与this Java question有关。
这是我的问题。我编写了一个应用程序,允许人们进行大量数据输入,在很多单独的字段中输入。为了确认每个字段的更改,他们通常可以点击 Return(对于单行字段)或 control-S(对于 Return 将是有效输入的多行字段),但这很麻烦,所以我还允许字段保存其内容当他们失去焦点时。所以用户可以type-tab-type,一切顺利。
除非他们更改了一个字段然后单击应用程序窗口的退出 X 的角落。他们预计这会被视为失去焦点,并将保存最后的更改。但是失去焦点事件并没有发生并且改变丢失了。
我可以添加一个完成按钮,它的副作用是移动焦点并保存最后一个字段,然后退出。但我不应该这样做。角落里有一个 X,它应该做正确的事情。
我的第一个想法是
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(.....
因为我认为我可以从那里向我的 SwingWorker 发布()一些东西,告诉它在所有事情上调用 lossFocus。没有这样的运气; publish() 受到保护。
基本上,当单击 X 时,我需要对各种小部件执行最后一项操作。我该怎么做?
编辑:我应该注意每个可编辑的小部件(下拉菜单、JTextPane 等)都已扩展为保存实际的相关数据。该小部件的所有数据,例如用户输入的值是否有效,在他编辑之前是什么,等等,都在那些扩展类实例中。没有其他地方值被保存;这不是模型视图控制器。
这样做的原因是小部件可以通过用户操作或网络消息进行更改;一条消息可能会完全丢弃现有的小部件,并用新内容替换它。换句话说,doInBackground 处于一个永久的读取循环中,读取网络更新消息并将这些更新请求发布()到 process()。用户操作像往常一样发生在对 process() 的调用之间。
底线,在退出时没有全局数据结构可以获取值。它们都在由 Swing 工作线程管理的数十到数百个数据结构中。应用程序本身,在那个 Swing 工作线程之外,甚至不知道存在什么样的值和小部件 - 所有小部件都是由来自服务器的网络消息。如果需要,应用程序的其余部分(几乎没有)无法安全地获取数据,除非我实现了大量的共享数据和锁定。
这一切都完美无缺,我不想为这个小小的关机案例重新设计它。我从来没有想过我无法从该线程外部将额外的“关闭”消息发布到 process() 的工作队列中。 (我的意思是线程安全队列很容易实现;为什么不呢?)
如果答案是“你不能在关机时和摇摆说话”,我会接受的。我确实有一个潜在的邪恶解决方法——我可以让 x 什么都不做,只向服务器发送一条消息,服务器可以写回一条“你应该关闭消息”,剩下的事情就可以完成了。但这似乎很笨拙。
【问题讨论】:
-
直接从
windowClosing()调用“保存”代码而不是尝试触发调用它的事件怎么样? -
把
publish方法的逻辑放到一个单独的public方法中,SwingWorker和WindowListener都可以调用。 -
角落里有一个X,它应该做正确的事。 - 正确的事通常意味着关闭窗口而不进行处理。大多数人认为它是一个“取消”按钮。通常应用程序(想想 Word、Excel)会检查数据是否已更改,然后会提示您是要“保存”还是“取消”。因此,我将向 WindowListener 添加逻辑以执行提示,然后根据需要调用“保存”方法。不确定 SwingWorker 与此有什么关系。
-
我看不出这与关机有什么关系。您需要处理甚至禁用窗口关闭事件。更好的是,您需要教育您的用户他们必须专门提交他们的更改。三十年来,我从来没有使用过一个可以为我做到这一点的应用程序。
-
@user207421:是的,这很不寻常。每个字段都会在焦点丢失时保存自己,因为保存是通过将更改发送到服务器来完成的 - 没有任何内容保存在本地 - 并且一些用户的网络连接可能会自发断开。如果他们做了 45 分钟的编辑然后全部丢失,我会被处以私刑。还有另一个原因是在本地不保存任何内容,并希望保存每个单独的更改 - 多个用户可以同时编辑同一个数据集合,因此更改需要转到服务器并或多或少地实时分发。