Java:使用 SwingUtilities.invokeLater() 进行调试
我使用 SwingUtilities.invokeLater()
频繁。然而,这样做在某些情况下会导致调试变得困难:您看不到调用 SwingUtilities.invokeLater()
的代码的堆栈跟踪,因为该代码已经结束了执行。
对于如何在调用 SwingUtilities.invokeLater()
时设置某种上下文(仅用于调试目的),以便您可以找出导致相关 UI 事件的原因,是否有任何建议?
I use SwingUtilities.invokeLater()
frequently. Doing so, however, makes it difficult to debug in certain cases: you can't see a stack trace of the code that called SwingUtilities.invokeLater()
, because that code has already ended its execution.
Are there any suggestions for how to set some sort of context (for debugging purposes only) when calling SwingUtilities.invokeLater()
, so that you can figure out what caused the UI event in question?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以尝试覆盖
EventQueue
并打印已发布事件的堆栈跟踪。此外,在下面的示例中,将为每个发布的事件分配一个唯一的编号。当从其他invokeLater
调用invokeLater
时,文本postEvent 9 from 7
将打印在日志中,其中类 MyEventQueue 可能如下所示:
You can try to override
EventQueue
and print stacktrace for posted events. Also in the example below a unique number would be assigned to each posted event. WheninvokeLater
would be called from otherinvokeLater
then the textpostEvent 9 from 7
would be printed in the logWhere class MyEventQueue might look like this:
这里的大多数其他答案都很好,但我想添加另一个建议。如果您非常频繁地调用 SwingUtilities.invokeLater,则有时您可能会不必要地执行此操作,特别是如果调用的唯一目的是确保在事件线程上进行 Swing 更改。适当的时候试试这个:
Most of the other answers here are good, but I want to add another suggestion. If you are calling SwingUtilities.invokeLater very frequently, you are probably doing it unnecessarily some of the time, especially if the sole purpose of the call is to ensure that Swing changes are made on the event thread. Try this when appropriate:
我倾向于用更高级的方法替换“标准”swingUtilites#invokeLater 方法,可能嵌入到一些“localUtilities”中,您可以将要执行的代码作为参数、源事件或线程安全副本提供给该方法它的(我猜你有一个源事件,无论它的类型是什么)。
I would tend to replace "standard" swingUtilites#invokeLater method by a more advanced one, maybe embedded in some "localUtilities", to which you give both the code to execute with, as an argument, the source event or a thread-safe copy of it (I guess you have a source event, whatever its type is).
重写该方法,添加一个 Log 调用,然后调用真正的方法......
警告:您必须替换对原始方法的所有调用。
您甚至可以包装可运行对象并添加上下文编号(例如稍后调用的调用的时间戳)。当可运行程序启动时,它开始打印上下文编号
Override the method, add a Log call and then call the real one...
Caveat : you have to replace all your calls to the original method.
You can even wrap the runnable and add a context number (for example the timestamp of the call to invoke later). When the runnable starts it began to print the context number
您是否将匿名
Runnable
传递给invokeLater()
?如果是,我建议将它们替换为非匿名类,这将添加几行代码,但至少会为您提供一定程度的可追溯性(例如:
TableUpdateFromQuery
)。如果您仅从应用程序中的一个位置调用特定类型的更新,则此方法效果最佳。它还引导您走上“后台活动”的道路,可以在 UI 之外进行测试。Are you passing anonymous
Runnable
s toinvokeLater()
?If yes, I'd suggest replacing them with non-anonymous classes, which will add a couple of lines of code, but will give you at least some level of traceability (eg:
TableUpdateFromQuery
). This works best if you invoke a particular type of update from only one place in the app. It also leads you down the path of "background activities," which can be tested outside of the UI.如果您频繁调用
invokeLater
,您可能需要考虑简化线程。invokeLater
有效地使用了可变静态,因此是最纯粹的邪恶。如果您从调用EventQueue.invokeLater
切换到使用带有invokeLater
和isDispatchThread
的接口,测试等将会变得更加容易。不幸的是,通常您无法替换库使用的
invokeLater
和isDispatchThread
。If you are calling
invokeLater
frequently, you might want to consider simplifying your threading.invokeLater
is effectively using mutable statics and is therefore purest evil. Testing and more will become easier if you switch from callingEventQueue.invokeLater
to using an interface withinvokeLater
andisDispatchThread
.It is unfortunate that you can't, in general, replace the
invokeLater
andisDispatchThread
used by libraries.