[英]Java JProgressBar does not show up by setVisible(true)
我有下面的方法。
ProgressWindow
是JFrame
的子类,其中包含JProgressBar
。
addProgress()
增加JProgressBar
的值。
如果我从另一个类的方法中调用此方法,则将显示ProgressWindow
框架,但不会显示JProgressBar
和框架中的某些JLabels
。 它们显示在最后一行( System.out.println("finish")
)之后。
如果在包含该方法的类的主方法中调用此方法,则每个组件(Bar,标签...)都会立即显示。
如何正确显示窗口?
static void search(){
ProgressWindow window = new ProgressWindow();
window.setVisible(true);
ExecutorService execs = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
Collection<Callable<Void>> processes = new LinkedList<>();
for (int i = 0; i < 100; i++) {
processes.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
progressWindow.addProgress(); // increment progress value
return null;
}
});
}
try {
execs.invokeAll(processes);
} catch (Exception e) {
e.printStackTrace();
} finally {
execs.shutdown();
}
System.out.println("finish");
听起来您想要执行的操作是在Swing UI线程上调用setVisible,您可以使用invokeAndWait或invokeLater进行此操作。
所以像这样:
final ProgressWindow window = new ProgressWindow();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
window.setVisible(true);
}
});
主要问题是您似乎从事件调度线程的上下文调用search
。
发生此问题的原因是您正在使用execs.invokeAll
,它将阻塞直到所有callables
都已运行完毕。
这意味着EDT无法处理事件队列中的新事件,包括重画事件,这就是为什么您的UI停滞不前的原因...
您现在要面对许多问题...
我们需要做的第一件事是通过某种方式通知搜索已完成,这意味着您不再可以依赖search
后返回的信息...
public interface SearchListener {
public void searchCompleted();
}
接下来,我们需要一个可互操作的search
方法,该方法可构建UI并确保在其自己的Thread
内启动搜索...
static void search(final SearchListener listener) {
final ProgressWindow window = new ProgressWindow();
window.setVisible(true);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
search(listener, window);
}
});
t.start();
}
然后我们需要修改原始search
方法以利用SearchListener
接口在搜索完成时提供通知...
static void search(final SearchListener listener, final ProgressWindow window){
ExecutorService execs = Executors.newFixedThreadPool(Runtime
.getRuntime().availableProcessors());
Collection<Callable<Void>> processes = new LinkedList<>();
for (int i = 0; i < 100; i++) {
processes.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
// This method needs to ensure that
// what ever it does to the UI, it is done from within
// the context of the EDT!!
progressWindow.addProgress();
return null;
}
});
}
try {
execs.invokeAll(processes);
} catch (Exception e) {
e.printStackTrace();
} finally {
execs.shutdown();
}
System.out.println("finish");
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
listener.searchCompleted();
}
});
}
现在,如果没有addProgress
的源代码,我可能会想使用
processes.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressWindow.addProgress();
}
});
return null;
}
});
}
代替...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.