I'm trying to show a JProgressBar in a Swing application used for communicating with a device using a SerialPort connection.
Sometimes the data that the device sends is large so it can take some time(5-10 seconds) to receive the data. Because of that, I want to show the user a progress bar so he knows that something is happening.
I tried doing this with JProgressBar and also with ProgressMonitor, but I just managed to show the progress window, but it just stayed at 0%.
Here is a method that I use to read the serialPort.
public static void readingDataSB9(SerialPort comPort) {
comPort.addDataListener(new SerialPortDataListener() {
@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
try {
if (serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
return;
}
//here I save the count data in the string array
List<String> countData = new ArrayList<>();
//here I save the text that is OCRed from the images
List<String> ocrText = new ArrayList<>();
//here I save the images from the machine
List<ImageIcon> serialImage = new ArrayList<>();
//trying to decode non UTF-8 strings from an array of Strings, only for TEST purposes
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
decoder.onMalformedInput(CodingErrorAction.IGNORE);
//Strings that represent the start of the serial number and new lines on each serial number
String startSn = "110000010011010001101100100011011000100011010000111000010001010";
String newLine = "01100000110110010001101100010001101000011100001000101";
int x = 0;
String s1 = "";
//getting InputStream from serial port and then converting it to BufferedStream, so it can be reset
//and read two times
InputStream in = comPort.getInputStream();
InputStream bufferdInputStream = new BufferedInputStream(in);
bufferdInputStream.mark(1000000000);
//I try to show progress of receiving data from InputStream
showProgress(bufferdInputStream, MainWindow.frame);
//first reading the input stream with scanner to get count data as Strings
Scanner sc = new Scanner(bufferdInputStream);
while (sc.hasNextLine()) {
countData.add(sc.next());
//this is the last string in the InputStream, so I use it to break from the while loop
if (countData.contains("\u001Bm\u001B3")) {
break;
}
}
System.out.println(countData);
//here I reset the InputStream, so it can be read again to receive the bytes needed to get the image
//of serial number
bufferdInputStream.reset();
while (((x = bufferdInputStream.read()) != 109)) {
//bytes are converted to binaryStrings, so I can get the binary image with Java Graphics library
s1 += String.format("%8s", Integer.toBinaryString(x & 0xFF)).replace(' ', '0');
}
//bytes are stored in the String array, they are split by String for the start of serial number
String[] binarySerialNumberArr = s1.split(startSn);
//here I immediately write the binaryString to the gui of MainWindow, so it can be saved to the database
MainWindow.jt_serialBinary.setText(String.join(", ", binarySerialNumberArr));
//here we take each element of String array and convert it from BinaryString to image
for (int i = 1; i < binarySerialNumberArr.length; i++) {
//first we create a empty image
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
Font font = new Font("Arial", Font.PLAIN, 2);
g2d.setFont(font);
int height = g2d.getFontMetrics().getHeight();
g2d.dispose();
//here we start to create the actual image of the serial number
img = new BufferedImage(384, 40, BufferedImage.TYPE_INT_RGB);
g2d = img.createGraphics();
g2d.setFont(font);
g2d.setColor(Color.WHITE);
int fontSize = 1;
for (String s : binarySerialNumberArr[i].split(newLine)) {
//we draw each string and use the newLine String to split the array element
//each 0 is represented as white, and 1 as black
g2d.drawString(s, 0, height);
height += fontSize;
}
//creating the image file
File file = new File("images\\Text" + i + ".png");
//saving the image to file
ImageIO.write(img, "png", file);
g2d.dispose();
//here we use the Tesseracts OCR library to get OCR text from image file
String ocrString = SerialOcr(file);
//here we fix some mistakes that OCR library does when doing OCR on images and add the data to
//OCR string array
ocrText.add(trainOcr(ocrString));
//we convert to image to ImageIcon and add it to ImageIcon array
serialImage.add(makeIcon(img));
System.out.println(ocrString);
}
//here we add ocrText to gui MainWindow
for (int i = 0; i < ocrText.size(); i++) {
MainWindow.model_ocrText.add(i, ocrText.get(i));
}
//here we add images to gui MainWindow
for (int i = 0; i < serialImage.size(); i++) {
MainWindow.model_serialImage.add(i, serialImage.get(i));
}
//here I try to ignore non UTF-8 string so I can get the OCR values from the machine also
//this is a TEST
ArrayList<String> validData = new ArrayList<>();
for (int i = 0; i < countData.size(); i++) {
decoder.decode(java.nio.ByteBuffer.wrap(countData.get(i).getBytes()));
validData.add(countData.get(i));
}
System.out.println(validData);
//checking to see what currency is the data from the machine, and building the gui table accordingly
for (int i = 0; i < countData.size(); i++) {
switch (countData.get(i)) {
case "RSD" -> insertRSD(countData, MainWindow.jt_denom);
case "USD" -> insertUSD(countData, MainWindow.jt_denom);
case "EUR" -> insertEUR(countData, MainWindow.jt_denom);
default ->
//in case none of the above currencies is chosen, we show the error message on JOptionPane
JOptionPane.showMessageDialog(null, "Odabrana valuta nije podržana", "Greška!", JOptionPane.ERROR_MESSAGE);
}
}
//after getting all the data to the gui table in MainWindow, we calculate the total count data
ButtonListeners.tableTotalAmountRows(MainWindow.jt_denom);
ButtonListeners.tableTotalAmountColumns(MainWindow.jt_denom);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Here is the showProgress method.
public static void showProgress(InputStream bufferedInputStream, JFrame frame) throws IOException {
JOptionPane pane = new JOptionPane();
pane.setMessage("Receiving data...");
JProgressBar jProgressBar = new JProgressBar(1, bufferedInputStream.available());
jProgressBar.setValue(bufferedInputStream.read());
pane.add(jProgressBar,1);
JDialog dialog = pane.createDialog(frame, "Information message");
dialog.setVisible(true);
dialog.dispose();
}
If someone has a better idea of how to show the progress, or just to keep the message on the screen while the data is being received, please feel free to suggest it.
Thanks in advance