Java 从其他线程更新Swing GUI

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

我有两个类,其中一个是我的线程,我在其中通过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();
消息在控制台中打印出来,但我无法将其值设置为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
}