Как запустить метод с JProgressBar - PullRequest
0 голосов
/ 24 декабря 2018

У меня есть функция с именем CreateAccount.Мне нужно, чтобы он работал, а также нужно показать индикатор выполнения.Когда я нажимаю кнопку, метод запускается.И мне нужно начать показывать индикатор загрузки.Когда метод завершен, индикатор выполнения также должен остановиться на 100. Если метод получает больше времени для выполнения работы, индикатор выполнения также должен загружаться медленно.

Я попытался использовать следующий код, но он не синхронизирует индикатор выполнения с методом.Так как я могу это сделать?

Вот мой код:

private static int t = 0;

private void createAccountBtnActionPerformed(java.awt.event.ActionEvent evt) {                                                 
        progressBar.setValue(0);
        progressBar.setStringPainted(true);

        new Thread(new Runnable() {
            @Override
            public void run() {
                //CreateAccount();

                for (t = 0; t <= 100; t++) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            CreateAccount();
                            progressBar.setValue(t);
                        }
                    });
                    try {
                        java.lang.Thread.sleep(100);
                    }
                    catch(InterruptedException e) { }
                }
            }
        }).start();
    }

Кто-нибудь может мне помочь?Заранее спасибо.

1 Ответ

0 голосов
/ 24 декабря 2018

Из-за однопоточной природы Swing вы не можете выполнять длительные или блокирующие операции в контексте потока диспетчеризации событий, а также не можете обновлять пользовательский интерфейс вне контекста потока диспетчеризации событий.

См. Параллельность в Swing для получения более подробной информации.

Обе эти вещи вы заботитесь.Проблема в том, что это означает, что фоновый поток может выполнять больше работы, чем было представлено в пользовательском интерфейсе, и с этим ничего не поделаешь.Лучшая ставка - просто стараться поддерживать пользовательский интерфейс в актуальном состоянии в максимально возможной степени

. Возможно, лучшим решением может быть использование SwingWorker, предназначенного для облегчения обновления пользовательского интерфейса.См. Рабочие потоки и SwingWorker для получения дополнительной информации.

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

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.time.Duration;
import java.time.Instant;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public final class Test {

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

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

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

    public class TestPane extends JPanel {

        private JProgressBar pb;
        private JButton btn;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            btn = new JButton("Go");
            pb = new JProgressBar();

            add(btn, gbc);
            add(pb, gbc);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    makeItProgress();
                }
            });
        }

        protected void makeItProgress() {
            SwingWorker<Double, Double> worker = new SwingWorker<Double, Double>() {
                @Override
                protected Double doInBackground() throws Exception {
                    Duration duration = Duration.ofSeconds(10);
                    Instant startTime = Instant.now();
                    Duration runningTime = Duration.ZERO;
                    Random rnd = new Random();
                    setProgress(0);
                    do {
                        Thread.sleep(rnd.nextInt(500));
                        Instant now = Instant.now();
                        runningTime = Duration.between(startTime, now);

                        double progress = (double) runningTime.toMillis() / (double) duration.toMillis();
                        setProgress((int) (progress * 100));
                    } while (duration.compareTo(runningTime) >= 0);
                    setProgress(100);
                    return 1.0;
                }
            };
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    SwingWorker worker = (SwingWorker) evt.getSource();
                    if (evt.getPropertyName().equals("progress")) {
                        int value = (int) evt.getNewValue();
                        pb.setValue(value);
                    } else if (evt.getPropertyName().equals("state") && worker.getState() == SwingWorker.StateValue.DONE) {
                        pb.setValue(100);
                        btn.setEnabled(true);
                    }
                }
            });
            worker.execute();
        }

    }

}

Суть этого примера в том, что выполнение и работа смешиваются в одну операцию (метод doInBackground в SwingWorker) поэтому они более тесно связаны.Затем SwingWoker уведомляет PropertyChangeListener об обновлениях, на которые он может безопасно реагировать в потоке диспетчеризации событий

...