JProgressbar замерзает, но я не использую Thread .sleep () [duplicate]

Метод stat () среди других атрибутов возвращает разрешения. d (например, drwxrwxrwx) показывает, что это каталог.

В качестве примера:

  dir = oct (sftp.stat (path) .st_mode) print dir [0:  2]  

выход interpritation: 01 fifo 02 характер специальный 04 каталог 06 блок специальный 10 обычный файл 12 символическая ссылка 14 гнездо

0
задан Zoyd 21 May 2014 в 21:54
поделиться

3 ответа

Ваш метод showProgress выполняется в контексте потока диспетчеризации событий. EDT отвечает за, среди прочего, обработку запросов краски. Это означает, что пока выполняется for-loop, EDT не может обрабатывать новые запросы на краску (или обрабатывать события invokeLater), поскольку он блокирует EDT.

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

Он имеет возможность разрешить вам выполнять (освобождение EDT), но также позволяет вам использовать средства для publishing обновлений (если требуется), чтобы они могли обрабатываться в EDT, а также обеспечивает удобное уведомление progress.

Например ...

enter image description here [/g2]

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
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;
import javax.swing.border.EmptyBorder;

public class SwingWorkerProgress {

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

    public SwingWorkerProgress() {
        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 JProgressBar pbProgress;
        private JButton start;

        public TestPane() {

            setBorder(new EmptyBorder(10, 10, 10, 10));
            pbProgress = new JProgressBar();
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(4, 4, 4, 4);
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(pbProgress, gbc);

            start = new JButton("Start");
            gbc.gridy++;
            add(start, gbc);

            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    start.setEnabled(false);
                    ProgressWorker pw = new ProgressWorker();
                    pw.addPropertyChangeListener(new PropertyChangeListener() {

                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            String name = evt.getPropertyName();
                            if (name.equals("progress")) {
                                int progress = (int) evt.getNewValue();
                                pbProgress.setValue(progress);
                                repaint();
                            } else if (name.equals("state")) {
                                SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
                                switch (state) {
                                    case DONE:
                                        start.setEnabled(true);
                                        break;
                                }
                            }
                        }

                    });
                    pw.execute();
                }
            });

        }
    }

    public class ProgressWorker extends SwingWorker<Object, Object> {

        @Override
        protected Object doInBackground() throws Exception {

            for (int i = 0; i < 100; i++) {        
                setProgress(i);
                try {
                    Thread.sleep(25);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            return null;
        }
    }
}

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

7
ответ дан MadProgrammer 15 August 2018 в 20:08
поделиться

Даже если вы исправите цикл, как указали другие, вы все равно заблокируете поток отправки событий. Цикл for запускается в showProgress(), который вызывается из прослушивателя событий. Обновления переносятся в очередь событий, но это не обрабатывается до тех пор, пока цикл не завершится.

Вместо этого используйте Swing Timer . Что-то вроде этого:

Timer timer = new Timer(25, new ActionListener() {
    private int position;

    @Override
    public void actionPerformed(ActionEvent e) {
         position++;
         if (position < lastPosition) {
             updateBar(position);
         } else {
             ((Timer) e.getSource).stop();
         }
    }
});
timer.start();

, где lastPosition будет состоянием, в котором вы хотите остановить индикатор выполнения.

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

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            JBarEx jbx = new JBarEx();
        }
    });
}
1
ответ дан kiheru 15 August 2018 в 20:08
поделиться
  • 1
    +1 для блокировки EDT, -1 для javax.swing.Timer, это не решит проблему, так как это вызовет только обратный вызов через равные промежутки времени. Есть лучшие решения ... – MadProgrammer 16 September 2013 в 21:05
  • 2
    @MadProgrammer работает с регулярными интервалами, что делает код вопроса. В зависимости от того, что делает приложение actual , конечно, SwingWorker может быть лучшим решением. – kiheru 16 September 2013 в 21:15
  • 3
    SwingWorker спроектирован именно для этой цели. Он может запускать задачу в фоновом режиме и предоставляет два способа для возврата к EDT, publish и setProgress. Не нужно пул для обновления, они автоматически отправляются. – MadProgrammer 16 September 2013 в 22:43
  • 4
    Я знаю это, и они очень полезны. Но все же они не всегда являются полным решением. Например, когда 1. требуемое время / шаги не определены, 2. фоновая задача не имеет хороших промежуточных шагов или вызов publish() будет беспорядочно ответственен, 3. фоновая задача не может быть использована для обновления статуса для других причины, например, это может заблокировать ожидание сетевого соединения. – kiheru 16 September 2013 в 22:50
  • 5
    Объединение состояния какой-либо фоновой задачи имеет все те же проблемы, которые вы только что указали. Нет никакой гарантии, что фоновая задача обновит что-нибудь полезное, поэтому вы просто тратите время на циклы процессоров. Поскольку SwingWorker - abstract, вы вынуждены / поощряетесь к тому, чтобы обеспечить надлежащую ответственность за обработку вывода, если это необходимо, потому что вы должны писать их для выполнения конкретной задачи. В случае «1» индикатор выполнения не является лучшим выбором (если вы не находитесь в неопределенном состоянии), тогда вам все равно не понадобится Timer ... – MadProgrammer 16 September 2013 в 22:56
for (int i = 0; i < 0; i++) {

Вы никогда не введете этот код, поэтому никогда не будете вызывать метод updateBar (..)

i в этом случае должен быть больше 0. Если это 1, то updateBar будет вызываться один раз, если 2, то updateBar будет вызываться дважды и т. Д.

Также вместо того, чтобы делать

Thread.sleep(25);

, посмотрите на java исполнителей , так как это поможет с вашим расписанием и устранит необходимость сна

0
ответ дан RNJ 15 August 2018 в 20:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: