1

I try to design a GUI for a neural network I made recently. I am using the MNIST-dataset and want to display the handwritten digit using JPanels with the brightness-values written inside. By pressing the "train"-button the network gets trained and every new digit is displayed. However this happens in a for loop in the actionperformed method of the button and it seems that I can´t change the background of the labels or the text(at least it doesn´t display the changes) until the last one. I don´t know whether I´m right but it seems that only the last change gets displayed. That´s why my question is whether it is possible to "refresh" the JFrame inside the actionperformed method.

I already have tried revalidate(), invalidate() & validate(), SwingUtilities.updateComponentTreeUI(frame), but none of them worked.

Here is the relevant part of my code:

train.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < iMax; i++) {
                ...
                digitRefresh(reader.getInputs()[i], (int) reader.getInputs()[i][0], 0);

            }
        }
    });

.

public void digitRefresh(double[] pixelValue, int target, int result) {
    for (int i = 0; i < 784; i++) {
        double value = pixelValue[i + 1];
        int brightness = (int) (value * 255);
        l_digit[i].setText(String.valueOf(value));
        l_digit[i].setBackground(new Color(brightness, brightness, brightness));
    }
    l_target.setText(String.valueOf(target));
    l_result.setText(String.valueOf(result));
    this.revalidate();
}

thank you for every awnser and sorry for my bad english.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Alexey
  • 15
  • 7
  • 1
    Swing does no redraws while your `actionPerformed()` method runs (the method runs on the same thread as the redraws). If you want to perform the `digitRefresh()` calls in parallel with UI redraws you have to run them in a separate worker thread. For examples see the [Lesson: Concurrency in Swing](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) from the official swing tutorials. – Thomas Kläger Mar 30 '20 at 07:26
  • You should consider using a SwingWorker, since you need to free the EDT. https://stackoverflow.com/q/782265/2067492 – matt Mar 30 '20 at 08:15

1 Answers1

1

The simplest thing to do is start a new thread.

    @Override
    public void actionPerformed(ActionEvent e) {
        new Thread( ()->{
        for (int i = 0; i < iMax; i++) {
            ...
            final int fi = i;
            EventQueue.invokeLater( ()->{
                digitRefresh(reader.getInputs()[fi], (int) reader.getInputs()[fi][0], 0);
            });

        }).start();
    }

Now all of the work is being done on a separate thread, then as the ... work finishes, digit refresh method called from the EDT. Notice the final int fi part. There are caveats about going back and forth on threads so it is good to look into better controls than just using thread.

Swing worker for example:

How do I use SwingWorker in Java?

matt
  • 10,892
  • 3
  • 22
  • 34