从其他线程更新Swing GUI

时间:2014-10-06 10:52:42

标签: 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 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文本:

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。

我需要一种快速实现此目的的方法,因此任何变通方法都将是最有帮助的。

谢谢,

1 个答案:

答案 0 :(得分:3)

如果当前主题 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()不会立即执行,而是在某个时间以后异步执行。如果您需要在返回之前进行更新,请使用SwingUtilities.invokeAndWait()

另请注意,您可以考虑使用SwingWorker类在后台线程中执行冗长的GUI交互任务。

制作实用方法

如果你必须多次这样做,为此制作一个实用的方法是有利可图的:

public void callFromEdt(Runnable task) {
    if (SwingUtilities.isEventDispatchThread())
        task.run();
    else
        SwingUtilities.invokeLater(task); // You might want to consider
                                          // using invokeAndWait() instead
}