本文介绍了从其他线程更新 Swing GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类,其中一个是我的线程,我在其中通过 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:48