gpt4 book ai didi

Java JProgressBar 不通过 setVisible(true) 显示

转载 作者:行者123 更新时间:2023-12-02 05:34:54 25 4
gpt4 key购买 nike

我有一个如下的方法。

ProgressWindow 是包含 JProgressBarJFrame 子类。

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");

最佳答案

主要问题是您似乎从事件调度线程的上下文中调用search

出现此问题的原因是您使用的 execs.invokeAll 会阻塞,直到所有 callables 完成运行为止。

这意味着 EDT 无法处理事件队列中的新事件,包括重绘事件,这就是您的 UI 停止运行的原因...

您现在将面临许多问题......

  1. 您永远不应该从 EDT 之外的任何线程更新/修改 UI 组件
  2. 无论出于何种原因,您都应该阻止 EDT
  3. 您似乎想知道搜索何时完成,因此您知道需要某种事件通知...

我们需要的第一件事是通过某种方式通知搜索已完成,这意味着您不能再依赖 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接口(interface)在搜索完成时提供通知...

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;
}
});
}

相反...

看看Concurrency in Swing了解更多详情

关于Java JProgressBar 不通过 setVisible(true) 显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25072648/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com