Счетчик в JFrame

#java #swing #jframe #event-dispatch-thread

#java #качать #jframe #событие-отправка-поток

Вопрос:

Я пытаюсь создать JFrame и увидеть ход работы счетчика.

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

Когда я запускаю его, я вижу прогресс на консоли, но значение textField не меняется. Он изменяется на 100000, когда цикл заканчивается.

Как я могу заставить его показывать прогресс, как в консоли?

Ответ №1:

Существует ряд важных различий между и другими инструментами графического интерфейса, такими как C #.

Во-первых, компоненты Swing ИМЕЮТ общий собственный одноранговый узел. Во многих других графических интерфейсах компоненты имеют свой собственный одноранговый узел, это влияет на контекст, в котором вы можете получить доступ к этим компонентам.

Во-вторых, поскольку компоненты Swing имеют общий собственный одноранговый узел, они по своей сути не являются потокобезопасными (например, все они используют одну и ту же очередь сообщений), это означает, что вы никогда не должны изменять компонент пользовательского интерфейса вне контекста потока отправки событий.

В-третьих, вы никогда не должны блокировать поток отправки событий, это помешает ему обрабатывать новые события, включая запросы на рисование.

В этом контексте вам, вероятно, следует использовать sa javax.swing.Timer , который позволит вам запланировать обратный вызов (который будет выполняться в контексте EDT) через регулярные промежутки времени, что делает его безопасным для использования, например, в контексте Swing framework…

 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);
        }
    }

}
  

Взгляните на параллелизм в Swing и как использовать таймеры Swing для получения более подробной информации…