2017-11-30 3 views
0

Ich versuche, Software zu schreiben, um Daten von drei seriellen RS232-Ports zu lesen, und ich habe Code geschrieben, um eine visuelle Rückmeldung zu geben, auf welchem ​​Port das Programm tatsächlich zu hören ist. Ich weiß, dass das Programm auf COM1 hört, da ich es auf der Konsole drucke, um mir zu sagen, welcher Port es hört. Das Problem ist, dass es die JTextFields nicht aktualisiert, um den Benutzer in der tatsächlichen GUI zu informieren. Der Code, den ich geschrieben habe, ist wie folgt:JTextField aktualisiert sich nicht von der seriellen Schnittstelle

if (Serial.currPortId == (null)) { 
     listenState.setText("NONE"); 
     listenState.revalidate(); 
    } 
    while (Serial.currPortId != (null)) { 
     listenState.setText(Serial.currPortId.getName()); 
     listenState.revalidate(); 
     if (Serial.currPortId.getName().equals("COM1")) { 
      tab1sheet.setText(ImportMenu.serialImport.datafeed); 
      tab1sheet.revalidate();} 
     else if (Serial.currPortId.getName().equals("COM2")) { 
      tab2sheet.setText(ImportMenu.serialImport.datafeed); 
      tab2sheet.revalidate();} 
     else if (Serial.currPortId.getName().equals("COM3")) { 
      tab3sheet.setText(ImportMenu.serialImport.datafeed); 
      tab3sheet.revalidate();} 
     else {tab1sheet.setText("N/A"); 
       tab1sheet.revalidate(); 
       tab2sheet.setText("N/A"); 
       tab2sheet.revalidate(); 
       tab3sheet.setText("N/A"); 
       tab3sheet.revalidate();} 
     } 

Aus irgendeinem Grund ist es immer nur die „listenState“ -Feld auf NONE einstellen und dann nicht aktualisiert, obwohl die behaupten, COM1 in der Konsole zu hören.

Antwort

1

Ihr Code bricht Swing Threading-Regeln. Es kann sein, dass Sie versuchen, den Listening-Code im Swing-Ereignisthread auszuführen (wir können nicht anhand des von Ihnen geposteten Snippets unterscheiden), aber es versucht sicherlich, das Textfeld in einem Thread schlecht zu aktualisieren. Stattdessen empfehle ich, dass Sie einen SwingWorker verwenden, um den Port in einem Hintergrundthread zu hören und speziell eine SwingWorker<Void, String>, die das publish/process-Methodenpaar verwendet, um Text an die JTextArea zu senden. Oder wenn Sie die GUI mit komplexeren Informationen aktualisieren müssen, die an mehrere Stellen der GUI gehen, dann fügen Sie einen PropertyChangeListener zu Ihrem SwingWorker hinzu, der alle Listener (die GUI) über Änderungen des Status des Arbeiters informiert.

Weitere Besuche Lesson: Concurrency in Swing

Ihr Code etwas könnte wie folgt aussehen:

class MyWorker extends SwingWorker<Void, Void> { 
    // properties to listen for changes to: 
    public static final String LISTEN_STATE = "listen state"; 
    public static final String CURRENT_PORT_ID = "current port id"; 
    public static final String DATA_FEED = "data feed"; 
    private String listenState = "None"; 
    private String dataFeed = ""; 
    private String currentPortId = ""; 

    @Override 
    protected Void doInBackground() throws Exception { 
     while (true) { 
      if (Serial.currPortId != (null)) { 
       // change properties when data comes in 
       String currPortId = Serial.currPortId.getName(); 
       setListenState(currPortId); 
       setCurrentPortId(currPortId); 
       setDataFeed(ImportMenu.serialImport.datafeed); 
      } else { 
       setListenState("None"); 
       break; // ?? 
      } 
     } 
     return null; 
    } 

    public String getListenState() { 
     return listenState; 
    } 

    public void setListenState(String listenState) { 
     // set the prop change parameters 
     String oldValue = this.listenState; 
     String newValue = listenState; 

     // update the propertie's state 
     this.listenState = listenState; 

     // notify listeners of the change 
     firePropertyChange(LISTEN_STATE, oldValue, newValue); 
    } 

    public String getDataFeed() { 
     return dataFeed; 
    } 

    public void setDataFeed(String dataFeed) { 
     // same rationale as for the other setter method 
     String oldValue = this.dataFeed; 
     String newValue = dataFeed; 
     this.dataFeed = dataFeed; 
     firePropertyChange(DATA_FEED, oldValue, newValue); 
    } 

    public String getCurrentPortId() { 
     return currentPortId; 
    } 

    public void setCurrentPortId(String currentPortId) { 
     // same rationale as for the other setter method 
     String oldValue = this.currentPortId; 
     String newValue = currentPortId; 
     this.currentPortId = currentPortId; 
     firePropertyChange(CURRENT_PORT_ID, oldValue, newValue); 
    } 
} 

Sie könnten dann einen Listener anhängen, die auf Veränderungen reagiert und dann aktualisiert die Anzeige in der GUI

private class MyWorkerListener implements PropertyChangeListener { 
    @Override 
    public void propertyChange(PropertyChangeEvent evt) { 
     switch (evt.getPropertyName()) { 
     case MyWorker.LISTEN_STATE: 
      String listenState = evt.getNewValue().toString(); 
      // show in text field 
      break; 
     case MyWorker.CURRENT_PORT_ID: 
      String currentPortId = evt.getNewValue().toString(); 
      // use this to decide which tab to change to 
      break; 
     case MyWorker.DATA_FEED: 
      String dataFeed = evt.getNewValue().toString(); 
      // show where needed 
      break; 

     default: 
      break; 
     } 
    } 
} 

und Sie würden es in der Gui wie:

verdrahten
MyWorker worker = new MyWorker(); 
worker.addPropertyChangeListener(new MyWorkerListener()); 
worker.execute(); 

würden Sie wollen auch eine andere Property zum Swingworker hinzuzufügen für die SwingWorker.StateValue.DONE newValue zu hören, und wenn es, rufen get() auf den Arbeiter zu stoppen auftritt und behandeln

alle Ausnahmen
+0

I‘ Ich schaue mir das an, danke! Der Hörcode wird in einer anderen Klasse ausgeführt, die hier über "Serial" aufgerufen wird. Es ist nur ein Fall, um es zu aktualisieren. Ich habe nicht viel Erfahrung mit seriellen Ports, also ist alles Lernen. –

+0

@JosephOliver: aber führen Sie den Abhörcode innerhalb eines Hintergrundthreads aus? Wenn nicht, würde ich erwarten, dass der Code Ihre GUI vollständig einfriert, so dass sie nicht mehr reagiert. –

+0

@JosephOliver: Bitte sehen Sie in der Antwort nach einem unvollständigen Beispiel. –

Verwandte Themen