[英]Java JProgressBar does not show up by setVisible(true)
I have a method like below. 我有下面的方法。
ProgressWindow
is a sub class of JFrame
containing JProgressBar
. ProgressWindow
是JFrame
的子类,其中包含JProgressBar
。
addProgress()
increments a value in the JProgressBar
. addProgress()
增加JProgressBar
的值。
If I call this method from a method in another class, a frame of ProgressWindow
will show up but not JProgressBar
and some JLabels
inside the frame. 如果我从另一个类的方法中调用此方法,则将显示ProgressWindow
框架,但不会显示JProgressBar
和框架中的某些JLabels
。 They show up after the last line ( System.out.println("finish")
). 它们显示在最后一行( System.out.println("finish")
)之后。
If I call this method in a main method in the class containing this method, then every component (Bar, labels...) instantly shows up. 如果在包含该方法的类的主方法中调用此方法,则每个组件(Bar,标签...)都会立即显示。
What can I do for showing the window correctly? 如何正确显示窗口?
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");
Sounds like you what you're wanting to do is invoke the setVisible on the Swing UI thread, you can do this with invokeAndWait or invokeLater . 听起来您想要执行的操作是在Swing UI线程上调用setVisible,您可以使用invokeAndWait或invokeLater进行此操作。
So something like: 所以像这样:
final ProgressWindow window = new ProgressWindow();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
window.setVisible(true);
}
});
The main problem is you seem to be calling search
from the context of the Event Dispatching Thread. 主要问题是您似乎从事件调度线程的上下文调用search
。
The problem occurs because you are using execs.invokeAll
which blocks until all the callables
have finished running. 发生此问题的原因是您正在使用execs.invokeAll
,它将阻塞直到所有callables
都已运行完毕。
This means that the EDT is unable to process new events in Event Queue, including repaint events, this is why your UI is coming to a stand still... 这意味着EDT无法处理事件队列中的新事件,包括重画事件,这就是为什么您的UI停滞不前的原因...
There are a number of issues you are now going to face... 您现在要面对许多问题...
The first thing we need is some way to be notified that the search has completed, this means you can no longer rely on search
returning when the search is complete... 我们需要做的第一件事是通过某种方式通知搜索已完成,这意味着您不再可以依赖search
后返回的信息...
public interface SearchListener {
public void searchCompleted();
}
Next we need an intermeditate search
method that builds the UI and ensure that the search is launched within it's own Thread
... 接下来,我们需要一个可互操作的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();
}
Then we need to modify the original search
method to utilise the SearchListener
interface to provide notification when the search is complete... 然后我们需要修改原始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();
}
});
}
Now, without the source code for addProgress
, I might be tempted to use 现在,如果没有addProgress
的源代码,我可能会想使用
processes.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressWindow.addProgress();
}
});
return null;
}
});
}
Instead... 代替...
Take a look at Concurrency in Swing for more details 查看Swing中的并发以了解更多详细信息
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.