- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题:我希望主应用程序窗口在所有工作线程停止后关闭。这很容易。但我也想确保 SwingWorker 发送的消息将在关闭窗口发送的消息之前得到处理。我这里有这个(不是那么)小示例源文件。
/*****************************************************************************
TestAsyncEvents.java
This example shows that messages from SwingWorker threads get processed
*AFTER* the WINDOW_CLOSED event even if they had been generated
*BEFORE* them.
The question is: HOW DO I MAKE IT RIGHT?
I know the answer, but it doesn't satisfy me. ;)
*****************************************************************************/
import java.util.List;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
//////////////////////////////////////////////////////////////////////////////
//
public class TestAsyncEvents extends JFrame
{
/*
* This class is for closing main window
*/
private class Closer extends WindowAdapter
{
@Override public void windowClosing( WindowEvent ev ) { handleWindowClosing(); }
@Override public void windowClosed( WindowEvent ev ) { handleWindowClosed(); }
}
/*
* This class represents worker that gets asked to stop
* and then reports when it actually stops
*/
private class Ticker extends SwingWorker<Boolean,String>
{
private boolean stop_flag = false;
private int counter = 0;
private boolean result;
Ticker() { super(); execute(); }
@Override protected Boolean doInBackground()
{
// body, executed in worker thread
try {
while( !stop_flag )
{
Thread.sleep(2000);
publish(String.format("Tick #%d",++counter));
}
return result=true;
} catch( Exception ex ) {
return result=false;
}
}
@Override protected void process( List<String> chunks )
{
// reports progress, executed in gui thread
for( String chunk: chunks )
System.out.println(String.format("Chunk processed: %s",chunk));
}
@Override protected void done()
{
// reports result, executed in gui thread
System.out.println(String.format("Thread is %s.",isCancelled()?"cancelled":"stopped normally"));
System.out.println(String.format("Result is %s.",Boolean.toString(result)));
//postClosing(); // IT IS THE SOLUTION FOR MY PROBLEM! BUT... IT ISN'T GOOD ONE!
}
public void askToStop() { stop_flag = true; }
}
/****************************************************************************/
/* FIELDS */
/****************************************************************************/
private static TestAsyncEvents self;
private Ticker worker_object = null;
/****************************************************************************/
/* CONSTRUCTOR */
/****************************************************************************/
TestAsyncEvents()
{
super("Testing Async Events");
addWindowListener(new Closer());
setMinimumSize(new Dimension(512,384));
setVisible(true);
worker_object = new Ticker();
}
/****************************************************************************/
/* INNER METHODS */
/****************************************************************************/
/*
* Waiting for worker to finish
*/
private void doStopping()
{
worker_object.askToStop();
while( !worker_object.isDone() );
}
private boolean stopInSeparateThread()
{
try {
Thread closer = new Thread(new Runnable(){public void run(){doStopping();}});
closer.start();
closer.join();
return true;
} catch( Exception ex ) {
return false;
}
}
private boolean stopHere()
{
doStopping();
return true;
}
private boolean stopWorker()
{
//return stopInSeparateThread();
return stopHere();
}
private boolean canClose()
{
return worker_object.isDone();
}
/*
* Posting WM_CLOSE events
*/
private void doPostCloseEvent()
{
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new WindowEvent(this,WindowEvent.WINDOW_CLOSING));
}
private void postInSeparateThread()
{
SwingUtilities.invokeLater(new Runnable(){public void run(){doPostCloseEvent();}});
}
private void postHere()
{
doPostCloseEvent();
}
private void postClosing()
{
//postInSeparateThread();
postHere();
}
/*
* Methods for Closer class
*/
private void handleWindowClosing()
{
System.out.println("Closing main window...");
if( canClose() )
{
System.out.println("Can close! Disposing...");
dispose();
} else {
System.out.println("Can't close! Now we'll allow it by stopping worker thread...");
boolean res = stopWorker();
System.out.println(String.format("Stopping worker thread went %s.",res?"okay":"wrong"));
postClosing(); // HERE I SIGNAL THE MAIN WINDOW TO CLOSE
}
}
private void handleWindowClosed()
{
System.out.println("Main window is closed!");
}
/****************************************************************************/
/* ENTRY POINT */
/****************************************************************************/
public static void main( final String[] args )
{
SwingUtilities.invokeLater(new Runnable(){public void run(){self=new TestAsyncEvents();}});
System.out.println("All systems are go!");
}
}
//////////////////////////////////////////////////////////////////////////////
它的输出在这里:
F:\C\Java\Test-Frame-Events>java TestAsyncEvents
All systems are go!
Chunk processed: Tick #1
Closing main window...
Can't close! Now we'll allow it by stopping worker thread...
Stopping worker thread went okay.
Closing main window...
Can close! Disposing...
Main window is closed!
Chunk processed: Tick #2
Thread is stopped normally.
Result is true.
我要的是这里:
F:\C\Java\Test-Frame-Events>java TestAsyncEvents
All systems are go!
Chunk processed: Tick #1
Closing main window...
Can't close! Now we'll allow it by stopping worker thread...
Stopping worker thread went okay.
Chunk processed: Tick #2
Thread is stopped normally.
Result is true.
Closing main window...
Can close! Disposing...
Main window is closed!
我突然想到,来自 SwingWorker 的事件是在一个完全不同的事件队列中处理的,而不是处理窗口消息等的事件队列。在我发布 WINDOW_CLOSING 事件之前,我故意等待工作线程停止并发布它的所有消息。但这没有帮助 - 来自 SwingWorker 的消息仍然在 WINDOW_CLOSING 和 WINDOW_CLOSED 事件之后得到处理。这会导致许多微小的不便。特别是,当我关闭 WINDOW_CLOSED 处理程序中的所有日志记录时,希望这些将是我程序中最后执行的运算符,来自工作线程的所有消息在时间和空间上都丢失了。
我知道我的问题的解决方案。我必须取消注释行 #68 和注释行 #161。但这意味着如果我有多个 SwingWorker 线程,我应该生成另一个线程来照顾所有工作人员,并在所有工作人员停止时向主窗口发出退出信号。恕我直言,这并不整洁。那么,Java 专家们,您建议我如何解决这个问题?
最佳答案
一种可能的解决方案:考虑使用 PropertyChangeListener:
private void handleWindowClosing() {
System.out.println("Closing main window...");
if (canClose()) {
System.out.println("Can close! Disposing...");
dispose();
} else {
System.out
.println("Can't close! Now we'll allow it by stopping worker thread...");
worker_object.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (SwingWorker.StateValue.DONE.equals(pcEvt.getNewValue())) {
postClosing();
}
}
});
boolean res = stopWorker();
System.out.println(String.format("Stopping worker thread went %s.",
res ? "okay" : "wrong")); // !!
// postClosing(); // HERE I SIGNAL THE MAIN WINDOW TO CLOSE
}
}
如果你有多个 worker ,你可以使用 CountDownLatch或 CyclicBarrier
关于java - 如何将 SwingWorker 与 Swing 同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12545098/
我正在开发一个摆动程序以显示多张图片。并且可以旋转图片(每个图片都以JComponent实现)。 问题是,当图片旋转时,JComponent的边框不会改变,因此图片会被剪切。 有什么办法也可以旋转边框
我有一个 JPanel 和一个 JButton 向量,我想将每个按钮添加到面板。 我遇到的问题是我有一个代表按钮向量的变量 btns,但宏函数只是将它视为一个符号,而不是一个向量。有没有办法以某种方式
我有一个 swing 应用程序,它覆盖 javax.swing.text.Document 以将基础文档的内容限制为某些字符和文本长度。我想将我的应用程序移植到 Javafx,但我不知道此类是否有 J
我有一个带有面板的简单应用程序,我想在单击它时暂停并重新开始绘画。 object ModulusPatterns extends SimpleSwingApplication { var dela
我似乎无法在 Swing 中强制布局。我有一个 JComponent添加到 JLayeredPane我在 JComponent 上设置了边框.然后,我想立即重新绘制所有内容 - 而不是像 invali
我有一个 Swing 应用程序,我想通过将外部文件从 Windows 资源管理器拖到应用程序上来导入外部文件。我有这个基本功能工作。但是,我想将默认的拖放光标图标更改为应用程序适当的光标。当鼠标键被按
我想在我的 Scala 摆动应用程序中使用一棵树,但该组件在 API 中不可用。 是否包装了 JTree存在吗? 如果没有,你对制作有什么建议吗? 谢谢 最佳答案 即使您可以在 Scala 程序中直接
我目前正在努力使我的 Swing 应用程序看起来更好。我想在这些方面实现一些目标: 这个想法是让每个框都有一个漂亮的标题,背景类似于上图。使用基本的 Swing 组件,我能得到的最接近的东西是添加 T
这是我在 Scala 中使用 Swing 的第一次实验,并且对下面的代码有一些疑问。它所做的只是生成一个带有可改变颜色的彩色矩形的窗口。请随时回答一个或任何一个问题。 1) 我在下面使用了 Java
一个愚蠢的问题,但我真的无法让它起作用:我在 Swing 应用程序中有一些长时间运行的过程,可能需要几分钟。我想在此过程进行时向用户显示进度对话框。我还想阻止用户执行进一步的操作,例如在进程进行时按下
如何获取秋千组件的默认背景色?我的意思是JPanel的默认背景色? 最佳答案 要获取创建面板时将使用的 DEFAULT 颜色,请使用: Color color = UIManager.getColor
我想更改特定表头的背景颜色。在我的应用程序中,我必须将当前月份的标题颜色设置为红色。 我的代码在这里:: jTable1.getTableHeader(). setDefaultRe
我正在努力使在 Java3D Canvas 上显示 Java Swing 组件并与之交互成为可能。我通过将透明 JPanel 绘制到缓冲图像来显示组件,然后使用 J3DGraphics2D 在 Can
嗨 当我在 swing 中创建按钮时,它会在文本周围添加边框,从而使按钮变大一点。 现在,我确实需要那个屏幕空间,我通常做的是创建一个文本项(禁用),它创建更小的组件大小(文本周围更小的空间)并向其添
有scala.swing.BoxPanel,但它似乎没有捕获重点,因为没有与javax.swing.Box工厂方法createHorizontalStrut等效的东西、createHorizo
我的 scala swing 应用程序中有一个 BoxPanel 按钮,这对我来说很难看,因为按钮的大小各不相同。我已将其更改为 GridPanel,但随后它们也垂直填充了面板,我发现这更难看。我怎样
我刚开始学习 Scala,作为学习过程的一部分,我一直在尝试使用 Swing 编写一些简单的脚本。 这是一个非常精简的例子,它展示了我所看到的问题。 SimpleSwingApp: import sc
我刚刚开始使用 clojure 和跷跷板制作 GUI 应用程序。它只创建一个 JFrame 和几个组件。这是代码。 main 函数除了调用 start-gui 什么也不做并在返回后立即退出。 (ns
Scala 是一种很棒的语言,但不幸的是缺少库文档。如何更改组件的初始大小?我什么都没有(故意),但无论如何都希望它是一定的。我目前有 ... contents = new BoxPanel(Orie
基本设置是这样的:我有一个垂直的 JSplitPane,我希望它有一个固定大小的底部组件和一个调整大小的顶部组件,我通过调用 setResizeWeight(1.0) 来完成。在此应用程序中,有一个按
我是一名优秀的程序员,十分优秀!