我试了好几个小时..我有一个线程改变了我的UI的JTextField,这完全破坏了UI。线程(让我们称之为线程A)由ActionListener生成。 .setText()函数调用在由线程A创建的额外线程(B)中。线程B是SwingUtilitis.invokeAll()和/或SwingUtilities.invokeAndWait()的参数。我试过了两个。这里有一些代码可以让它更清晰。
这是我创建线程A的ActionListener - 当然缩短了:
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == window.getBtn_Search()) {
Refresher refresh = new Refresher();
refresh.start();
}
}
这是我的线程A,后来将线程B放入EDT队列:
public class Refresher extends Thread implements Runnable {
private int counter = 0;
private UI window = null;
private int defRefresh = 0;
@Override
public void run() {
while(true){
-bazillion lines of code-
do {
try {
Refresher.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(window.canceled()) break;
UI.updateCounter(window.getLbl_Status(), (Configuration.getRefreshTime()-counter));
counter++;
} while (counter <= Configuration.getRefreshTime());
- more code-
}
}
}
UI.updateCounter(...)将线程B排入EDT。
public static void updateCounter(final JLabel label, final int i) {
try {
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
label.setText("Refreshing in: " + i + " seconds.");
}
}
);
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
现在,当调用最后一个函数时,一切都搞砸了。我尝试了几个小时不同的东西,没有任何效果我也尝试过使用SwingWorker,但有些甚至根本没有发生。
答案 0 :(得分:0)
一般来说,标签不是很擅长显示更改的文字:它们的宽度变化以及带有它的布局。
使用只读JTextField,可能是样式的适当更改,可能是更好的解决方案。
答案 1 :(得分:0)
我认为您创建的中间JPanel
可能算作验证根。因此,当您调用revalidate()
时自动发生的setText()
不会导致任何布局更改高于JPanel
父级别。
我认为您实际上不需要面板,因为JLabel
可以包含图标和文本。请参阅the tutorial。
所以我的建议是删除面板,如果它们用于某个目的,请确保面板上的isValidateRoot()
返回false。
答案 2 :(得分:0)
invokeAndWait()
尝试允许发布要在EDT上执行的Runnable任务,但它会阻止当前线程并等待EDT完成执行任务。
但是invokeAndWait()中存在死锁的可能性,因为在任何代码中都存在创建线程相互依赖性的问题。 如果调用代码保持一些代码调用的锁(显式或隐式) 通过invokeAndWait()需要,那么EDT代码将等待非 EDT代码释放锁定,因为非EDT代码不可能发生 正在等待EDT代码完成,应用程序将挂起。
正如我们在这里看到的,修改等待非传递的JLabel组件 EDT代码。
我们可以使用
invokeLater()
需要
关心创建和排队包含Runnable的特殊事件。该事件按照收到的顺序在EDT上处理,就像任何其他事件一样。
到时候,运行Runnable的run()方法调度它。
SwingUtilities.invokeLater(new Runnable() {
public void run() {
label.setText("Refreshing in: " + i + " seconds.");
}
});
或强>
isEventDispatchThread()
如果调用代码当前正在EDT上执行则返回true,否则返回false。
Runnable code= new Runnable() {
public void run() {
label.setText("Refreshing in: " + i + " seconds.");
}
}
);
if (SwingUtilities.isEventDispatchThread()) {
code.run();
} else {
SwingUtilities.invokeLater(code);
}
答案 3 :(得分:-1)
更改label
的文字时,您至少应在repaint()/revalidate()
最顶层的容器上调用label
,触发重新布局,假设为{{ 1}}在文本更改时正确调用label
/ invalidate()
。