user3358377
user3358377

Reputation: 145

Counter on JFrame

I am trying to make a JFrame and see the progress of the counter.

int i = 1;
while (i < 100000){
    textField.setText(String.valueOf(i));
    System.out.println(i);
    i++;
}

When I start it I can see the progress at the console but the value of the textField does not change. It changes to 100000 when the loop ends.

How can I make it show the progress like in console?

Upvotes: 1

Views: 4492

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

There are a number of important differences between and other GUI toolkits like C#.

Firstly, Swing components SHARE a common native peer. In many other GUI frameworks, components have their own native peer, this affects the context in which how you can access these components.

Secondly, because Swing components share a common native peer, there are inherently un-thread safe (they all share the same message queue for example), this means you should never modify a UI component out side of the context of the Event Dispatching Thread.

Thirdly, you should never block the Event Dispatching Thread, this will prevent it from process new events, including paint requests.

In this context, you should should probably use s a javax.swing.Timer, which will allow you to schedule a callback (which will occur within the context of the EDT) at a regular interval, making it safe to use within the context of the Swing framework, for example...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Counter {

    public static void main(String[] args) {
        new Counter();
    }

    public Counter() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel label;
        private Timer timer;
        private int count;

        public TestPane() {
            label = new JLabel("...");
            setLayout(new GridBagLayout());
            add(label);
            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    count++;
                    if (count < 100000) {
                        label.setText(Integer.toString(count));
                    } else {
                        ((Timer)(e.getSource())).stop();
                    }
                }
            });
            timer.setInitialDelay(0);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }

}

Take a look at Concurreny in Swing and How to Use Swing Timers for more details...

Upvotes: 3

Related Questions