当我启动我的应用程序时,它会打开JFrame
(主窗口)和JFilechooser
以选择输入目录,然后扫描该目录。
扫描方法本身会创建一个包含JFrame
和JButton
的新JProgressBar
,并启动一个扫描所选目录的新线程。到目前为止一切正常。
现在我在主窗口中更改目录路径,再次调用扫描方法。这次它创建了另一个JFrame
,其中应包含JProgressBar
和JButton
,但它显示为空(JFrame
标题仍然设置。)
更新: 最小的例子
public class MainWindow
{
private JFrame _frame;
private JTextArea _textArea;
private ProgressBar _progress;
public MainWindow() throws InterruptedException, ExecutionException
{
_frame = new JFrame("Main Window");
_textArea = new JTextArea();
_frame.add(_textArea);
_frame.setSize(200, 200);
_frame.setVisible(true);
_textArea.setText(doStuffinBackground());
_progress.dispose();
}
private String doStuffinBackground() throws InterruptedException,
ExecutionException
{
setUpProgressBar();
ScanWorker scanWorker = new ScanWorker();
scanWorker.execute();
return scanWorker.get();
}
private void setUpProgressBar()
{
// Display progress bar
_progress = new ProgressBar();
}
class ProgressBar extends JFrame
{
public ProgressBar()
{
super();
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
progressBar.setStringPainted(false);
add(progressBar);
setTitle("Progress Window");
setSize(200, 200);
toFront();
setVisible(true);
}
}
class ScanWorker extends SwingWorker<String, Void>
{
@Override
public String doInBackground() throws InterruptedException
{
int j = 0;
for (int i = 0; i < 10; i++)
{
Thread.sleep(1000);
j += 1;
}
return String.valueOf(j);
}
}
public static void main(String[] args) throws InvocationTargetException,
InterruptedException
{
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
// Start the main controller
try
{
new MainWindow();
}
catch (InterruptedException | ExecutionException e) {}
}
});
}
}
答案 0 :(得分:2)
从scan
方法的基本外观来看,当您扫描目录时阻止了事件调度线程,这阻止了它更新UI。
具体来说,您似乎并不真正了解Callable
和FutureTask
实际使用的内容或如何正确使用它们......
调用FutureTask#run
将从当前线程上下文中调用Callable
的{{1}}方法....
请查看Concurrency in Swing了解更多详情......
不要试图以这种方式使用call
和FutureTask
,而是考虑使用Callable
,它旨在执行此类工作(并使用SwingWorker
和内部Callable
有关详细信息,请查看Worker Threads and SwingWorker
现在,在你跳下我的喉咙并告诉我“它第一次运行它”时,这是因为你没有正确启动你的UI。应该在Event Dispatching Thread的上下文中创建和操作所有Swing UI。你执行FutureTask
方法,通常称为“主线程”,它与EDT不同。这基本上设置了第一次调用main
时的侥幸情况,你没有在EDT的上下文中运行,允许它工作......并且在这个过程中打破了Swing的单线程规则。 ..
请查看Initial Threads了解更多详情......
我还会考虑使用scan
代替另一个框架,即使它不是模态的,它也可以为您的应用程序提供更好的范例,因为它实际上应该只有一个主框架。
根据新代码更新
所以,基本上,JDialog
是一个阻止调用。它将等到return scanWorker.get();
方法完成,这意味着它阻止了EDT,仍然......“
相反,您应该使用doInBackground
publish
,process
和/或done
方法
SwingWorker