Как я могу перекрасить ярлык во время обработки в Swing? - PullRequest
2 голосов
/ 05 августа 2011

Я новичок в Swing, и я пытался сделать это:

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

Проблема в том, что текст метки не обновляется, пока цикл не завершит итерацию по всем элементам.

Я искал в Интернетеи, очевидно, это потому, что это выполняется в том же потоке, поэтому я создал новый поток для обработки данных и обновления переменной, которая будет использоваться в метке (количество обработанных файлов).

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

Код такой:

btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            try { SwingUtilities.invokeLater(validateFiles); } 
}); }

Runnable validateFiles = new Runnable() {

    @Override
    public void run() {
                 while(x_is_not_100) {
                      processLoadsOfStuff();
                      label.setText(x); }
            }
};

Можете ли вы помочь мне с этим?

Ответы [ 2 ]

7 голосов
/ 05 августа 2011

Простой - используйте SwingWorker.Для получения дополнительной информации прочитайте учебник Задачи, которые имеют промежуточные результаты .


Вот довольно общий пример, который будет использовать JLabel для отображения счета от 0 до 30 -

public final class SwingWorkerDemo {
    private static JLabel label = 
        new JLabel(String.valueOf(0), SwingConstants.CENTER);

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                createAndShowGUI();             
            }
        });

        JLabelSwingWorker workerThread = new JLabelSwingWorker();
        workerThread.run();
    }

    private static void createAndShowGUI(){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(label);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static class JLabelSwingWorker extends SwingWorker<Void, Integer>{
        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 1; i < 31; i++){
                Thread.sleep(1000);
                publish(i);
            }
            return null;
        }

        @Override
        protected void process(List<Integer> integers) {
            Integer i = integers.get(integers.size() - 1);
            label.setText(i.toString());
        }
    }
}
6 голосов
/ 05 августа 2011

Фоновая обработка должна выполняться в отдельном потоке. Но обновление метки должно быть сделано в потоке отправки событий.

Итак, ваш код должен выглядеть так:

btnNewButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // start a new thread for the background task
        new Thread(validateFiles).start(); 
    }); 
}

Runnable validateFiles = new Runnable() {

    @Override
    public void run() {
             while(x_is_not_100) {
                  processLoadsOfStuff();
                  // use SwingUtilities.invokeLater so that the label update is done in the EDT:
                  SwingUtilities.invokeLater(new Runnable() {
                      @Override
                      public void run() {
                          label.setText(x);
                      }
                  });
             }
    };

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...