1


Ich arbeite an Software für die Lagerverwaltung (zum Speichern von Kleidung). Alle Artikel im Warehouse haben eine RFID-Funktion mit einer eindeutigen ID, die als String gespeichert ist.
Ich versuche ein Modul zu erstellen, das es Benutzern erlaubt, rfid von Element zu Antenne zu lesen und die empfangene ID automatisch in einem der GUI jLabels anzuzeigen. Die Antenne ist über rs232 mit dem PC verbunden.
Ich habe es geschafft, Klasse zu machen, um Daten von Antenne zu lesen, und es funktioniert gut. Es öffnet den Port für die Kommunikation, legt Eigenschaften fest und liest Daten, wenn sie verfügbar sind (über SerialPortEvent.DATA_AVAILABLE event).
Aber dann habe ich Problem festgestellt:
Ich möchte Instanz dieser Klasse in verschiedenen Thread so Antenne wird auf Scan und jedes Mal nach dem Scan jLabel wird entsprechend der ID des Artikels geändert werden (später werde ich komplexer werden Operationen auf dieser ID mit meiner Datenbank verbunden, aber jetzt will ich nur, dass es irgendwo angezeigt wird).
Ich beginne mein Java-Abenteuer und ich weiß nicht, wie man Multithreading behandelt.
In diesem Fall würde ich gerne von meinem Netbeans GUI jFrame aus scannen und während der Scanvorgang läuft, sollte der jFrame Wert von jLabel entsprechend dem zuletzt gescannten Element dynamisch aktualisieren.
Szenario:
Benutzer drückt auf die Schaltfläche, um den Scanvorgang zu starten, scannt einige Objekte, die ID jedes gescannten Objekts wechselt zwischen den Scans zu jLabel (jReadLabel). Wenn der Scanvorgang abgeschlossen ist, drückt der Benutzer die Taste, um anzuhalten Faden.
Ich habe Getter-Methode in meiner ReadCOM-Klasse (getChipID()) gemacht, aber ich weiß nicht, wie Sie Daten an jFrame jedes Mal übergeben, wenn Ereignis aufgetreten ist. Hier ist das, was ich bisher getan:Java - dynamische Änderung jLabel Text nach Daten von der seriellen Schnittstelle

import java.io.*; 
import java.util.*; 
import javax.comm.*; 

public class ReadCOM implements Runnable, SerialPortEventListener { 

static CommPortIdentifier portId; 
static CommPortIdentifier saveportId; 
static Enumeration portList; 
InputStream inputStream; 
SerialPort serialPort; 
public static Thread readThread; 
static OutputStream outputStream; 
static boolean outputBufferEmptyFlag = false; 
public String defaultPort; 
boolean isRunning = true; 
private String chip_id=""; 

public CzytajCOM(CommPortIdentifier portId, String defaultPort) { 

    this.defaultPort = defaultPort; 
    try { 
     serialPort = (SerialPort) portId.open("Magazyn", 2000); 
    } catch (PortInUseException e) { 
     System.out.println("Connection Error. Port in use."); 
    } 

    try { 
     inputStream = serialPort.getInputStream(); 
    } catch (IOException e) { 
    } 

    try { 
     serialPort.addEventListener(this); 
    } catch (TooManyListenersException e) { 
    } 
    serialPort.notifyOnDataAvailable(true); 
    try { 
     serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, 
       SerialPort.STOPBITS_1, 
       SerialPort.PARITY_NONE); 
    } catch (UnsupportedCommOperationException e) { 
    } 
    readThread = new Thread(this); 
    readThread.start();  
} 

public void initwritetoport() { 

    try { 
     outputStream = serialPort.getOutputStream(); 
    } catch (IOException e) { 
    } 

    try { 
     serialPort.notifyOnOutputEmpty(true); 
    } catch (Exception e) { 
     System.exit(-1); 
    } 

} 

public void writetoport() { 
} 

public void run() { 

    while (isRunning) { 
     try { 
      while (isRunning) { 
       Thread.sleep(100); 
      } 
     } catch (Exception e) { 
      isRunning = false; 
     } 
    } 
} 

public void serialEvent(SerialPortEvent event) { 
    switch (event.getEventType()) { 
     case SerialPortEvent.BI: 
     case SerialPortEvent.OE: 
     case SerialPortEvent.FE: 
     case SerialPortEvent.CD: 
     case SerialPortEvent.CTS: 
     case SerialPortEvent.DSR: 
     case SerialPortEvent.RI: 
      break; 

     case SerialPortEvent.OUTPUT_BUFFER_EMPTY: 
      break; 

     case SerialPortEvent.DATA_AVAILABLE: 

      Object obj = event.getSource(); 
      if (obj instanceof javax.comm.SerialPort) { 
       serialPort = (SerialPort) obj; 
       try { 
        BufferedReader bufferedReader = new BufferedReader(
        new InputStreamReader(serialPort.getInputStream())); 
        chip_id = bufferedReader.readLine(); 
        //System.out.println("Data: "+chip_id); 
        bufferedReader.close(); 
       } catch (Exception ex) { 
        System.out.println("Reading from device failed!"); 
       } 
      } 
      break; 
    } 
} 

public boolean isRunning() { 
    return isRunning; 
} 

public String getChipId() { 
    return chip_id; 
} 

public void setIsRunning(boolean isRunning) { 
    this.isRunning = isRunning; 
} 

} Und in meiner JFrame Datei hier ist der Code von ButtonActionPerformed (die Taste, die beginnt und aufhört zu lesen, dem Teil, wo im verloren ...):

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed 
    if(isRead==false) { 
      jStatus.setText("Reading in progress..."); 
      jLabel1.setText("Press the button to stop reading."); 
      isRead=true; 
      try { 
     portId1=CommPortIdentifier.getPortIdentifier("COM4"); 
     ReadCOM reader=new ReadCOM(portId1, portId1.getName()); 
     reader.setIsRunning(true); // 
     jReadLabel.setText(reader.getChipId()); 
       } 
    catch (Exception ex){ 
        System.out.println("Error in button pressed method."); 
        } 
    } 
       else { 

     jStatus.setText("Reading stopped."); 
     jLabel1.setText("Press the button to start reading."); 
     isRead=false; 
    } 
}//GEN-LAST:event_jButton1ActionPerformed  
+1

Sie das EDT (Event Dispatch Thread) nicht blockieren - die GUI wird ‚einzufrieren‘ wenn das passiert. Statt '' 'Thread.sleep (n)' aufzurufen, implementieren Sie einen Swing 'Timer' für wiederkehrende Aufgaben oder einen' SwingWorker' für lang andauernde Aufgaben. Siehe [Parallelität in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) für weitere Details. (etwas später, aber mit 'der Link'). –

Antwort

1

1) Methode setText() als Gewinde sicher erklärt, sondern arbeitet, bis aktuelle Thread

von Thread.sleep(int), nicht vereist

2) Verfahren setText() Arbeiten aus Runnable#run() oder util.Timer#run() in invokeLater() gewickelt, aber Ihre Thread.sleep(int) ist außerhalb dieser APIs , dann möglicherweise Ereignisse an den EventDispatchThread

3) Sperren können Sie CommPort von ActionListener öffnen, dann Swing-GUI-freeze ist oder nicht unresponsible, bis alle Ereignisse ist von ActionListener endete, nichts konnte b e dispayed in JLabel

4) Sie (Lesewert von CommPort) auf die Hintergrundaufgabe

  • aufrufen CommPort von Runnable.Thread oder aus util.Timer (dann nicht erforderlich Pausieren Schleife bewegen müssen Thread.sleep() durch)

aber die meisten besser und ich würde vorschlagen,

  • i zu verwenden, nvoke von SwingWorker, dann können Sie Thread.sleep() oder util.Timer innerhalb Methode doInBackground() und Ausgabe von Methoden publish() oder process() Ereignisse aufrufen könnte auf EDT
+0

Entschuldigung für Verspätung, ich bin seit fast einem Monat nach Autounfall verletzt:/Vielen Dank für Ihre Tipps @mKorbel - das war genau das, was ich brauchte! Ich habe den Ansatz von SwingWorker mit dem Ereignisverteiler publish (chip_id) verwendet und es funktioniert jetzt einwandfrei. Prost. – demo

+0

froh, Ihnen zu helfen – mKorbel

1

Von Ihrem seriellen Port-Lese Thread dies auszuführen:

SwingUtilities.invokeLater(new Runnable() { public void run() { 
    // code that updates the label's contents 
}}); 

es ist also ein Push-Ansatz: Sie die rfid nicht ziehen Sie es in die GUI, takin drücken Es ist besonders wichtig, dass ein solcher Code auf dem Event-Dispatching Thread (EDT) ausgeführt wird. Das ist, was invokeLater ist.