i’m working on software for warehouse management (for storing clothes). All items in warehouse have rfid inside, with unique id stored as a String.
I’m trying to make module that will allow users to read rfid from item by antenna and automatically show received ID in one of GUI’s jLabels. Antenna is connected with PC by rs232.
I’ve managed to make class to read data from antenna and it works fine. It opens port to communication, sets properties and reads data when available (through SerialPortEvent.DATA_AVAILABLE event).
But then I’ve encountered problem:
I want instance of that class running in different thread so antenna will be waiting for scan and every time after scan jLabel will be changed according to item’s ID (later on i will be doing more complex operations on this ID connected with my database but now i just want it to be shown somewhere).
I’m beginning my Java adventure and I don’t know how to handle multithreading.
In this case I would like to start scanning from my Netbeans GUI jFrame and while the scanning will be in progress the jFrame should dynamically refresh value of jLabel according to last scanned item.
Scenario:
User presses the button to start scanning, scans some ammount of items, ID of each scanned item goes to jLabel (jReadLabel) for the time between scans, and when scanning is complete user presses button to stop, so app knows when to stop the thread.
I’ve made getter method in my ReadCOM class (getChipID()) but i don’t know how to pass data to jFrame every time when event occured.
Here is what I’ve done so far:
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;
}
}
And in my jFrame file here’s the code of ButtonActionPerformed (the button which starts and stops reading, the part where im lost…):
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) method
setText()is declared as thread safe but works untill current thread isn’t freezed byThread.sleep(int),2) method
setText()works wrapped intoinvokeLater()fromRunnable#run()orutil.Timer#run(), but yourThread.sleep(int)is outside of those APIs, then potentially can locking events to theEventDispatchThread3) you opening
CommPortfromActionListener, then Swing GUI is freeze or isn’t unresponsible untill all events fromActionListenerended, nothing could be dispayed inJLabel4) you have to move (reading value from CommPort) to the Background task
CommPortfromRunnable.Threador fromutil.Timer(then not required pausing loop by usingThread.sleep())but most better and I’d suggest to use
SwingWorker, then you can useThread.sleep()orutil.Timerinside methoddoInBackground()and output from methodspublish()orprocess()could be invoke events onEDT