Swing popup screen with progress bar

This is my screensaver code,

public class SplashScreen extends JWindow { private static final long serialVersionUID = 1L; private BorderLayout borderLayout = new BorderLayout(); private JLabel imageLabel = new JLabel(); private JProgressBar progressBar = new JProgressBar(0, 100); public SplashScreen(ImageIcon imageIcon) { imageLabel.setIcon(imageIcon); setLayout(borderLayout); add(imageLabel, BorderLayout.CENTER); add(progressBar, BorderLayout.SOUTH); pack(); setLocationRelativeTo(null); } public void showScreen() { SwingUtilities.invokeLater(new Runnable() { public void run() { setVisible(true); } }); } public void close() { SwingUtilities.invokeLater(new Runnable() { public void run() { setVisible(false); dispose(); } }); } public void setProgress(final String message, final int progress) { SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(progress); if (message == null) { progressBar.setStringPainted(false); } else { progressBar.setStringPainted(true); } progressBar.setString("Loading " + message + "..."); } }); } } 

From the main method that I call this way

 public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { try { UIManager.setLookAndFeel(UIManager .getSystemLookAndFeelClassName()); SplashScreen splashScreen = new SplashScreen(new ImageIcon("images/splash.jpg")); splashScreen.showScreen(); AppFrame frame = new AppFrame(splashScreen); } catch (Exception e) { appLogger.error(e.getMessage(), e); } } }); } 

In the AppFrame constructor, I call the splashScreen.setProgress (msg, val) method to update the progress bar. But the surge is not displayed. It is displayed only at the end, when the frame is displayed only for a split second, even if the download takes a long time. But if I put these three lines

 SplashScreen splashScreen = new SplashScreen(new ImageIcon("images/splash.jpg")); splashScreen.showScreen(); AppFrame frame = new AppFrame(splashScreen); 

outside of invokeLater (), a splash screen is displayed, and the progress bar updates beautifully. I believe GUI updates should be in invokeLater. What could be the problem?

Btw, AppFrame loads various panels of my application.

Edit: Below is the layout of my AppFrame.

 public class AppFrame extends JFrame { public AppFrame(SplashScreen splashScreen) { JPanel test = new JPanel(); test.setLayout(new GridLayout(0, 10)); splashScreen.setProgress("jlabel", 10); for(int i = 0; i < 10000; i++) { test.add(new JButton("Hi..." + i)); splashScreen.setProgress("jbutton", (int)(i * 0.1)); } add(new JScrollPane(test)); setPreferredSize(new Dimension(800, 600)); pack(); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setLocationRelativeTo(null); splashScreen.setProgress("complete", 100); setVisible(true); } } 
+6
source share
3 answers

And invokedLater is called from another invokeLater . runnable will only execute when the first completes.

You should modify the Splashscreen code as follows:

 ... private void runInEdt(final Runnable runnable) { if (SwingUtilities.isEventDispatchThread()) runnable.run(); else SwingUtilities.invokeLater(runnable); } public void showScreen() { runInEdt(new Runnable() { public void run() { setVisible(true); } }); } public void close() { runInEdt(new Runnable() { public void run() { setVisible(false); dispose(); } }); } public void setProgress(final String message, final int progress) { runInEdt(new Runnable() { public void run() { progressBar.setValue(progress); if (message == null) progressBar.setStringPainted(false); else progressBar.setStringPainted(true); progressBar.setString("Loading " + message + "..."); } }); } 
+2
source

Take a look at this working sample that I am using, which uses the SplashScreen class (uses only Timer and ActionListener to increase the ProgressBar to 100 and the frame is displayed):

 import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.event.ActionListener; import javax.swing.*; public class SplashScreen extends JWindow { private static JProgressBar progressBar = new JProgressBar(); private static SplashScreen splashScreen; private static int count = 1, TIMER_PAUSE = 25,PROGBAR_MAX=100; private static Timer progressBarTimer; ActionListener al = new ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent evt) { progressBar.setValue(count); System.out.println(count); if (PROGBAR_MAX == count) { splashScreen.dispose();//dispose of splashscreen progressBarTimer.stop();//stop the timer createAndShowFrame(); } count++;//increase counter } }; public SplashScreen() { createSplash(); } private void createSplash() { Container container = getContentPane(); JPanel panel = new JPanel(); panel.setBorder(new javax.swing.border.EtchedBorder()); container.add(panel, BorderLayout.CENTER); JLabel label = new JLabel("Hello World!"); label.setFont(new Font("Verdana", Font.BOLD, 14)); panel.add(label); progressBar.setMaximum(PROGBAR_MAX); container.add(progressBar, BorderLayout.SOUTH); pack(); setLocationRelativeTo(null); setVisible(true); startProgressBar(); } private void startProgressBar() { progressBarTimer = new Timer(TIMER_PAUSE, al); progressBarTimer.start(); } private void createAndShowFrame() { JFrame frame = new JFrame(); frame.setSize(500, 500); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { splashScreen = new SplashScreen(); } }); } } 
+4
source
  Thread l_splash_thread = new Thread( new SplashScreen ()); l_splash_thread.start(); try { l_splash_thread.join(); } catch (InterruptedException e1) { e1.printStackTrace(); } 

I think that you can hold your bursts.

0
source

Source: https://habr.com/ru/post/922714/


All Articles