1

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

0 Answers0