Search code examples
javaswinguser-interfacejlabel

Why does my JFrame not show my label


I have this loadpanel to show to the user when my program is exporting the video. So when the export button is clicked, I do this:

loadframe = new LoadFrame("Video Exporteren...");

This creates the dialog and shows it on the screen. Yet, it takes about 5 seconds before the actual label on the dialog is shown. Can anyone tell me why. Thanks

public LoadFrame(String operation) {

    mainloadframe = new JDialog();
    JLabel operationlabel = new JLabel(operation);
    loadpanel = new JPanel();

    mainloadframe.setSize(300, 75);
    mainloadframe.setLocationRelativeTo(null);
    mainloadframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    mainloadframe.setAlwaysOnTop(true);
    mainloadframe.setTitle(operation);
    mainloadframe.setResizable(false);

    loadpanel.add(operationlabel);
    mainloadframe.add(loadpanel);
    mainloadframe.setVisible(true);

}

Solution

  • Swing uses a single thread model. This means that interactions with the UI (create/modify) are executed within a single thread, known as the Event Dispatching Thread.

    The RepaintManager uses the EDT to schedule repaint requests. If something blocks the EDT, these paint requests (and other events) won't be processed.

    Swing is also not thread safe. This means you are expected to create and modify the UI only from within the context EDT.

    The problem you have, is you are blocking the EDT with a time consuming process, meaning that the EDT can't process any events until your long-running task is complete.

    There are a number of solutions.

    You Could...

    Use a background thread to perform the time consuming operation. This leads to the next problem of how to you tell the UI when something has changed (ie, provide progress updates or that the process has completed).

    You could use SwingUtilities.invokeLater to re-sync updates with UI. This places a Runnable onto the EDT, ensuring that the run method is executed within in the context of the EDT.

    You Could...

    Use a SwingWorker. A SwingWorker has methods to automatically re-sync with EDT, allowing you to publish/process changes within the EDT as well as a done method which is executed within the context of the EDT after its doInBackground method completes.

    This is probably the simplest to the methods as it all nicely self contained.

    Check out Concurrency in Swing for more details