Java 从其他线程更新Swing GUI
我有两个类,其中一个是我的线程,我在其中通过TCP/IP读取设备的输出:Java 从其他线程更新Swing GUI,java,swing,sockets,event-dispatch-thread,Java,Swing,Sockets,Event Dispatch Thread,我有两个类,其中一个是我的线程,我在其中通过TCP/IP读取设备的输出: public static controlPanel cp = new controlPanel(); void startListenForTCP (final String ipaddress){ Thread TCPListenerThread; TCPListenerThread = new Thread(new Runnable() { @Override public voi
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();
消息在控制台中打印出来,但我无法将其值设置为jLabel
我需要一个快速的方法来实现这一点,所以任何解决办法都将是最有帮助的
谢谢,您的代码仅在当前线程不是EDT时更新GUI:
if (!SwingUtilities.isEventDispatchThread()) {
// you call SwingUtilities.invokeLater();
}
如果当前线程恰好是EDT,GUI更新也应该发生。所以你应该把它改成这样:
if (SwingUtilities.isEventDispatchThread())
jLabel5.setText(text);
else
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
jLabel5.setText(text);
}
});
请注意,invokeLater()
不会立即执行,而是在一段时间后异步执行。如果需要在更新返回之前进行更新,请使用
还注意到,您可以考虑使用类在后台线程中执行冗长的GUI交互任务。
实用化方法 如果您必须多次这样做,那么为其制定一个实用的方法是有利可图的:public void callFromEdt(Runnable task) {
if (SwingUtilities.isEventDispatchThread())
task.run();
else
SwingUtilities.invokeLater(task); // You might want to consider
// using invokeAndWait() instead
}
您可能需要使用
SwingWorker
类而不是普通线程。您能在这个示例中演示如何实现这一点吗?给您:我得到了这个错误:线程“AWT-EventQueue-0”java.lang.StackOverflower中的异常位于java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)在java.awt.EventQueue.isDispatchThreadImpl(EventQueue.java:1035)在java.awt.EventQueue.isDispatchThread(EventQueue.java:1030)在javax.swing.SwingUtilities.isEventDispatchThread(SwingUtilities.java:1361)在tryout.controlPanel.updateGUI(controlPanel.java:305)在tryout.controlPanel.updateGUI(controlPanel.java:306)在java在tryout.controlPanel.updateGUI(controlPanel.java:306)
第306行是updateGUI(text)代码>我不知道您从自身调用了相同的方法updateGUI()
。我更新了代码。仍然没有,如果我从线程调用方法updateGUI,什么都不会发生,但是当我从表单(点击按钮)调用它并传递一些文本时,所有内容都在jlabel中打印出来。但是对于线程,它不起作用,然后尝试使用SwingUtilities.invokeAndWait()
代替invokeLater()
。顺便说一句,您是否阻止了EDT?即使使用invokeAndWait(),仍然没有任何结果。7我真的不明白,这就是我在上面问题中应用程序的全部代码。
public void callFromEdt(Runnable task) {
if (SwingUtilities.isEventDispatchThread())
task.run();
else
SwingUtilities.invokeLater(task); // You might want to consider
// using invokeAndWait() instead
}