Interestingly, I recently encountered a similar problem, so in order to overcome this, I used SwingUtilities.invokeAndWait (Runnable runnable) , which made SSCCE I created for work as expected, although if I change all the calls to invokeAndWait ( ) with invokeLater () , the difference between the two things is clearly visible.
A quote from the Java Doc says:
Causes doRun.run() to be executed synchronously on the AWT event dispatching thread. This call blocks until all pending AWT events have been processed and (then) doRun.run() returns. This method should be used when an application thread needs to update the GUI.
This is a small program that I did as SSCCE to represent bubble sort animation:
import javax.swing.*; public class BubbleSortFrame extends JFrame { private BubbleSortView contentPane; private void displayGUI() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); contentPane = new BubbleSortView(); setContentPane(contentPane); pack(); setLocationByPlatform(true); setVisible(true); } public static void main(String... args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new BubbleSortFrame().displayGUI(); } }); } }
import java.awt.*; import java.awt.event.*; import java.lang.reflect.InvocationTargetException; import javax.swing.*; public class BubbleSortView extends JPanel { private JLabel sizeLabel; private JTextField sizeField; private JTextField[] vField; private JLabel[] vLabel; private JButton startButton, createButton; private int size; private JPanel createPanel, animationPanel; private BubbleSort bubbleSort; public BubbleSortView() { size = 5; displayAndCreateGUI(); } private void displayAndCreateGUI() { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); setOpaque(true); setBackground(Color.WHITE); JPanel basePanel = new JPanel(); basePanel.setLayout(new GridLayout(2, 1, 5, 5)); basePanel.setOpaque(true); basePanel.setBackground(Color.WHITE); JPanel topPanel = new JPanel(); topPanel.setOpaque(true); topPanel.setBackground(Color.WHITE); topPanel.setBorder( BorderFactory.createTitledBorder("Input : ")); topPanel.setLayout(new GridLayout(2, 1, 5, 5)); JPanel sizePanel = new JPanel(); sizePanel.setOpaque(true); sizePanel.setBackground(Color.WHITE); sizeLabel = new JLabel("Enter Number of Elements : "); sizeField = new JTextField(10); createButton = new JButton("CREATE"); createPanel = new JPanel(); createPanel.setOpaque(true); createPanel.setBackground(Color.WHITE); createPanel.setBorder( BorderFactory.createTitledBorder("Please Enter values for an Array : ")); createPanel.setVisible(false); animationPanel = new JPanel(); animationPanel.setOpaque(true); animationPanel.setBackground(Color.WHITE); animationPanel.setBorder( BorderFactory.createTitledBorder("Animation : ")); animationPanel.setVisible(false); createButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { if (sizeField.getDocument().getLength() > 0) { size = Integer.parseInt(sizeField.getText()); vField = new JTextField[size]; createPanel.setVisible(true); for (int i = 0; i < size; i++) { vField[i] = new JTextField(5); if (i == (size - 1)) { vField[i].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent ae) { animationPanel.setLayout( new GridLayout(1, size, 2, 2)); animationPanel.setVisible(true); vLabel = new JLabel[size]; for (int i = 0; i < size; i++) { vLabel[i] = new JLabel( vField[i].getText(), JLabel.CENTER); vLabel[i].setOpaque(true); vLabel[i].setBackground(Color.YELLOW); vLabel[i].setForeground(Color.RED); animationPanel.add(vLabel[i]); } animationPanel.revalidate(); animationPanel.repaint(); bubbleSort = new BubbleSort(vLabel, size); Thread t = new Thread(bubbleSort); t.start(); } }); } createPanel.add(vField[i]); } createPanel.revalidate(); createPanel.repaint(); createButton.setEnabled(false); } else size = 5; } }); sizePanel.add(sizeLabel); sizePanel.add(sizeField); sizePanel.add(createButton);
source share