Как настроить прогресс бар JProgressBar?

197
23 декабря 2019, 11:40

Как сделать JProgressBar чтобы он работал на кнопку Jbutton и заканчивал работу после того как прогресс дошел до 100%?

Answer 1

Для выполнения продолжительных задач (а иначе зачем вам JProgressBar) в Swing есть специальный механизм SwingWorker, oн внутри имеет механизм передачи информации о выполняемой задаче, я сделал небольшой пример, правда он не отражает некоторых аспектов работы SwingWorker, но показывает как правильно работать с JProgressBar:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Dimension;

public class SwingWorkerAndProgressBarExample {
    public static void main(String[] args) {
        JProgressBar progress = new JProgressBar();
        JButton button = new JButton("start");
        button.addActionListener(e -> {
            startWorker(progress, button).execute();
            button.setEnabled(false);
            button.setText("please wait");
        });
        JFrame frame = new JFrame("SwingWorkerAndProgressBarExample");
        frame.setLayout(new BorderLayout());
        frame.add(progress, BorderLayout.NORTH);
        frame.add(button, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(400,100));
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    private static SwingWorker<Void, Void> startWorker(JProgressBar progress, JButton button) {
        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() {
                for (int i = 0; i < 100 && !isCancelled(); i++) {
                    doWork();
                    setProgress(i);
                }
                return null;
            }
            @Override
            protected void done() {
                button.setEnabled(true);
                button.setText("start again");
                progress.setValue(0);
            }
        };
        worker.addPropertyChangeListener(e -> {
            if ("progress".equals(e.getPropertyName())) {
                progress.setValue((Integer)e.getNewValue());
            }
        });
        return worker;
    }
    private static void doWork() {
        try {
            Thread.sleep(40);
        } catch (InterruptedException ignored) {}
    }
}

Типы, которые надо описать для создания SwingWorker (в моем примере <Void, Void>) это типы возвращаемых данных, первый это тип конечного результата работы воркера, второй - тип промежуточного результата (chunk'a) который может быть опубликован вызовом метода publish() в рамках работы метода doInBackground() и обработан при помощи переопределения метода process():

class SimpleTask extends SwingWorker<String, Integer> {
     @Override
     public List<Integer> doInBackground() {
         doWork();
         publish(1983)
         ...
         doWork();
         publish(2019)
         ...
         return "OK";
     }
     @Override
     protected void process(List<Integer> chunks) {
         ...
     }
 }
Answer 2
public class Main {
    private static JProgressBar bar;
    private static AtomicInteger x = new AtomicInteger(0);
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setBounds(50, 50, 400, 400);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());
        bar = new JProgressBar(JProgressBar.HORIZONTAL);
        bar.setMinimum(0);
        bar.setMaximum(100);
        bar.setValue(0);
        bar.setPreferredSize(new Dimension(200, 20));
        frame.getContentPane().add(bar);
        JButton btn = new JButton("Go!");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (x.get() < 100) {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    x.addAndGet(10);
                                    bar.setValue(x.get());
                                    bar.repaint();
                                }
                            });
                        }
                    }
                }).start();
            }
        });
        frame.getContentPane().add(btn);
        frame.setVisible(true);
    }
}

В реальном коде конечно использование статических переменных минимизируйте. Ну и надо помнить, что прорисовка элементов и обработка событий происходит в отдельном специальном потоке Event Dispatch Thread. Поэтому из главного потока нельзя менять визуальные компоненты - надо работать через Event Dispatch Thread (вызов invokeLater).

READ ALSO
Как правильно отобразить один item в RecyclerView?

Как правильно отобразить один item в RecyclerView?

Необходимо чтобы не весь список сразу отображался, а по очереди с 0 до listsize(), если пользователь свайпнул

145
Recycler view, Android

Recycler view, Android

У меня есть фрагмент, он хранит список CardView и допинформацию(назову ее "информация A")

122
Вернуть статус ответа на GraphQL

Вернуть статус ответа на GraphQL

Пишу API на GraphQL, с которым работает фронтэнд-приложениеНужно возвращать фронтэндеру что-то вроде status OK и error 404

175
Почему надо обязательно использовать Try - catch

Почему надо обязательно использовать Try - catch

Есть программа на Java в которой допустим (к примеру) есть функция отображение списка категорий, который берется из базы данных через mysql запросЕсть...

163