0

i'm trying to update Swing JSLable text before processing loop, but it's not updating:

public void actionPerformed(ActionEvent event)
{     
    title.setText("Ready"); // Initialize display
    if (source == uploadButton) {
        int returnVal = fc.showOpenDialog(UserInterface.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File[] files = fc.getSelectedFiles();
            if (files.length < 2) {
                title.setText("<html>Text1</html>"); // Is shown
            } else {
                title.setText("<html>Text2</html>"); // Not displaying, feels like UI is locked here

                for (int i = 0; i < files.length; i++) {
                    filesUploaded.add(uploadFile(files[i]));
                }

                Images imgs = new Images();
                imgs.processImages(filesUploaded); // Some processing loop inside, takes around 0.5~1s
                title.setText("Completed"); // displayed corectly.
            }
        }
    }
}

So basically i wish to have sequence:

Ready
Text2
Completed

but i get this sequence (with missing Text2 output):

Ready
Completed
apxcode
  • 7,696
  • 7
  • 30
  • 41
Justinas
  • 41,402
  • 5
  • 66
  • 96

5 Answers5

2

The GUI thread is blocked, you should wrap this part of code into SwingUtilities.invokeLater:

SwingUtilities.invokeLater(new Runnable() {

    for (int i = 0; i < files.length; i++) {
        filesUploaded.add(uploadFile(files[i]));
    }

    Images imgs = new Images();
    imgs.processImages(filesUploaded); // Some processing loop inside, takes around 0.5~1s
    title.setText("Completed"); // displayed corectly.
});

BTW, C-style for loops are not appreciated in Java, you should use "enhanced for" construction:

for (File file: files)
  filesUploaded.add (files);

Or even

filesUploaded.addAll(Arrays.asList(files))
Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48
0

That is ok because you block the GUI thread (action is performed in that thread) and it won't update before you exit the method.

Look for "block gui thread java". You'll find that often happens in actionPerformed.

Val
  • 1
  • 8
  • 40
  • 64
0

Swing works on Single Threaded Model and that thread of Swing application is called EDT (EventDispatchThread) Its always suggested not to do any heavy processing on this thread because it will block UI thread and your UI will become un-responsive for that duration. I would suggest moving the file upload part in a separate thread to keep your UI responsive.

And use SwingUtilities.invokeLater to schedule any UI related work on EDT from this separate thread.

Another approach may be to use SwingWorker

Sanjeev
  • 9,876
  • 2
  • 22
  • 33
  • invokeLater will not help to avoid the repainting issue. Only SwingWorker – Sergiy Medvynskyy May 22 '14 at 09:38
  • It will certainly help in this scenario as the heavy work will be done in the separate thread and after all this heavy work if UI needs to be updated then put that through invokeLater. – Sanjeev May 22 '14 at 09:41
0

Use SwingWorker or Foxtrot to implement your long running Task. Your long running task blocks the EDT (Event Dispatcher Thread - main Swing thread) and the Repaint event which must come after event processing cannot be executed.

Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
0

You should put those HTML tags somewhere else, since it confuses swing when you put text outside of HTML. E.g. You should put the opening tag before the ready word and the closing tag after the completed string. You should also know that the setText method overwrites the text in the element. You should use:

setText(object.getText()+"Text");

For example

title.setText("<HTML>Ready");
//...
title.setText(title.getText()+"Text2");
//...
title.setText(title.getText()+"Completed</HTML>");

Please note that the actionPerformed() method is called by the event dispatch thread which manages the Graphical User Interface and you are using it for a lengthy task. This freezes the GUI since the EDT is not avaliable for updating the GUI. Use a different thread instead:

Thread t=new Thread(new Runnable(){
  public void run(){
    <your code here>
  }
});

Also if you are accessing swing, Java recommends doing it on the event thread, like when you are calling setText() or something similar:

SwingUtilities.invokeLater(new Runnable(){
  public void run(){
    <your code to access swing>
  }
});