问题描述
我有两个类,其中一个是我的线程,我在其中通过 TCP/IP 从设备读取输出:
I have two classes, one of them is my thread in which I read outputs from a device through TCP/IP:
public static controlPanel cp = new controlPanel();
void startListenForTCP (final String ipaddress){
Thread TCPListenerThread;
TCPListenerThread = new Thread(new Runnable() {
@Override
public void run() {
Boolean run = true;
String serverMessage = null;
InetAddress serverAddr = null;
BufferedWriter out = null;
try
(Socket clientSocket = new Socket(ipaddress, 7420)) {
cp.updateGUI("Connection initiated... waiting for outputs!"+"\n");
char[] buffer = new char[2];
int charsRead = 0;
out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((charsRead = in.read(buffer)) != -1)
{
String message = new String(buffer).substring(0, charsRead);
switch (message) {
case "o,":
cp.updateGUI("Čekanje da loptica prođe RFID čitač!");
break;
case "y,":
cp.updateGUI("Hardverski problem!");
break;
case "Y,":
cp.updateGUI("Loptica nije izažla, hardverski problem!");
break;
case "I,":
cp.updateGUI("Uređaj u stanju mirovanja!!");
break;
default:
String m = message;
m = m.replaceAll("[^\\d.]", "");
try{
int i = Integer.parseInt(m);
System.out.println("Is int: "+i);
int izasao=Integer.parseInt(m);
if (redni>34){
redni=0;
}
if (izasao>0 && izasao<49){
redni =redni+1;
m=m;
ur.updateResults(redni, m);
bs.testAuto(m, redni);
System.out.println(m+ "\n");
}
} catch(NumberFormatException e){
} break;
}
}}
catch(UnknownHostException e) {
System.out.println("Unknown host..."+"\n");
} catch(IOException e) {
System.out.println("IO Error..."+"\n");
}
}
});
TCPListenerThread.start();
}
另一种是swing形式,我想在上面的类中设置jLabel文本:
The other one is swing form in which i want to set jLabel text from the class above:
Public class controlPanel extends javax.swing.JFrame {
public static gameControler gc = new gameControler();
public controlPanel() {
initComponents();
}
public void updateGUI(final String text) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
updateGUI(text);
}
});
}jLabel5.setText(text);
System.out.println(text);
}
该消息在控制台中打印出来,但我无法将其值设置为 jLabel.
The message gets printed out in console but i can't set it's value to jLabel.
我需要一种快速的方法来实现这一目标,因此任何变通方法都将是最有帮助的.
I need a quick way to achieve this, so any workarounds will be most helpfull.
谢谢,
推荐答案
如果当前线程不是 EDT,您的代码仅更新 GUI:
Your code only updates the GUI if current thread is not the EDT:
if (!SwingUtilities.isEventDispatchThread()) {
// you call SwingUtilities.invokeLater();
}
如果当前线程恰好是 EDT,GUI 更新也应该发生.所以你应该把它改成这样:
The GUI update should also happen if the current thread happens to be the EDT. So you should change it to somehting like this:
if (SwingUtilities.isEventDispatchThread())
jLabel5.setText(text);
else
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
jLabel5.setText(text);
}
});
请注意,invokeLater()
不会立即执行,而是在一段时间后异步执行.如果您需要在它返回之前进行更新,请使用 SwingUtilities.invokeAndWait()
.
Note that invokeLater()
is not executed immediately but asynchronously some time later. If you need the update to happen before it returns, use SwingUtilities.invokeAndWait()
.
另请注意,您可以考虑使用 SwingWorker
类在后台线程中执行冗长的 GUI 交互任务.
Also note that you may consider using the SwingWorker
class to perform lengthy GUI-interaction tasks in a background thread.
如果你必须多次这样做,为此制作一个实用方法是有利可图的:
If you have to do this many times, it is profitable to make a utilitiy method for this:
public void callFromEdt(Runnable task) {
if (SwingUtilities.isEventDispatchThread())
task.run();
else
SwingUtilities.invokeLater(task); // You might want to consider
// using invokeAndWait() instead
}
这篇关于从其他线程更新 Swing GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!