简体   繁体   English

进度栏未使用线程更新

[英]progress bar not updating with threads

ok, I'm here again to ask one dummy question. 好吧,我再次在这里问一个假的问题。 I have a custom dialog frame and have progress bar on it. 我有一个自定义对话框框,上面有进度栏。 So also I have a genetic algorithm (which works pretty big amount of time). 所以我也有一个遗传算法(它工作的时间很多)。

As I understand all the situation, I need to execute separate threads for algorithm, progress bar and leave the main thread for the dialog (to give him an opportunity to respond to user actions). 据我所知,我需要为算法,进度条执行单独的线程,并在对话框中保留主线程(以便他有机会响应用户的操作)。 So I tried to implement this, and got the following: 因此,我尝试实现此目标,并获得了以下信息:

public class ScheduleDialog extends JDialog {

    private final JPanel contentPanel = new JPanel();

    private static Data data;
    private static GeneticEngine geneticEngine;
    private static Schedule schedule;

    private static JProgressBar progressBar;
    private static JLabel statusLabel;

    public static void showProgress() {
        try {
            ScheduleDialog dialog = new ScheduleDialog();
            dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dialog.setVisible(true);
            startScheduleComposing();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void startScheduleComposing() {
        BackGroundWorker backGroundWorker = new BackGroundWorker();
        GeneticEngineWorker geneticEngineWorker = new GeneticEngineWorker();
        new Thread(geneticEngineWorker).start();
        new Thread(backGroundWorker).start();
    }

    private ScheduleDialog() {

        this.data = Data.getInstance();

        setTitle("");
        setModal(true);
        setBounds(100, 100, 405, 150);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension dialogSize = getSize();
        setLocation((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2);
        getContentPane().setLayout(new BorderLayout());
        contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        getContentPane().add(contentPanel, BorderLayout.CENTER);
        contentPanel.setLayout(new GridLayout(0, 1, 0, 0));
        {
            progressBar = new JProgressBar();
            progressBar.setBackground(Color.RED);
            contentPanel.add(progressBar);
        }
        {
            statusLabel = new JLabel("");
            contentPanel.add(statusLabel);
        }
        {
            JPanel buttonPane = new JPanel();
            buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
            getContentPane().add(buttonPane, BorderLayout.SOUTH);
            {
                JButton okButton = new JButton("Прервать");
                okButton.setActionCommand("OK");
                buttonPane.add(okButton);
                getRootPane().setDefaultButton(okButton);
            }
        }


    }

    protected static class BackGroundWorker implements Runnable {
        @Override
        public void run() {
          while(true){
            int barValue = 100 - (geneticEngine.getCurrentBestFitness() / geneticEngine.getInitialFitness());
            progressBar.setValue(barValue);
            progressBar.repaint();
            statusLabel.setText(String.valueOf(geneticEngine.getCurrentBestFitness()));
            statusLabel.repaint();
            try{
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();  
            }
          }
        }
    }

    protected static class GeneticEngineWorker implements Runnable{

        @Override
        public void run() {
            geneticEngine = new GeneticEngine(data);
            schedule = geneticEngine.GeneticAlgorithm();
        }
    }
}

it seems, that new Thread(geneticEngineWorker).start(); 看来, new Thread(geneticEngineWorker).start(); is working but nothing happens with progress bar. 正在工作,但进度条没有任何反应。 I think this part of code: 我认为这部分代码:

private static void startScheduleComposing() {
            BackGroundWorker backGroundWorker = new BackGroundWorker();
            GeneticEngineWorker geneticEngineWorker = new GeneticEngineWorker();
            new Thread(geneticEngineWorker).start();
            new Thread(backGroundWorker).start();
        }

we get new Thread(backGroundWorker).start(); 我们得到new Thread(backGroundWorker).start(); executed only after new Thread(geneticEngineWorker).start(); 仅在new Thread(geneticEngineWorker).start();之后执行new Thread(geneticEngineWorker).start(); will be stopped. 将停止。
So if I'm right could you please tell me how code can be reorganized to make the work, and if I'm wrong could you point me to my mistakes? 因此,如果我是对的,请告诉我如何重组代码以完成工作,如果我错了,可以指出我的错误吗?

Thanks everyone in advance! 提前谢谢大家!


ADDITION 加成

I debuged it and as I thought, backGroundWorker starts working only after geneticEngineWorker ends or user closes dialog(exception in this case); 我调试了它,并且我以为,backGroundWorker仅在GeneticEngineWorker结束或用户关闭对话框之后才开始工作(在这种情况下为例外);

yes there are two basics ways by using 是的,有两种基本的使用方法

SwingWorker , required deepest knowledge about Java Essential Classes inc. SwingWorker ,需要有关Java Essential Classes inc的最深入的知识。 Generics too Generics

and

Runnable#Thread required only wrapping output to the GUI into invokeLater() Runnable#Thread只需要将输出到GUI的包装到invokeLater()

simple example about no special effort required for idea Runnable#Thread , JProgressBar all in JTable , thats means that code line model.setValueAt(value, row, column); 一个简单的示例,它不需要在JTable中将想法Runnable#ThreadJProgressBar全部花费在JTable ,这意味着代码行为model.setValueAt(value, row, column); should be wrapped into invokeLater , but in other hands setText() is declared as thread safe, I'd to suggest wrapping that into invokeLater in all cases 应该包装到invokeLater ,但另一方面, setText()被声明为线程安全的,在所有情况下,我建议将其包装到invokeLater

在此处输入图片说明在此处输入图片说明

import java.awt.Component;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class TableWithProgressBars {

    private static final int maximum = 100;

    public void createGUI() {
        final JFrame frame = new JFrame("Progressing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Integer[] oneRow = {0, 0, 0, 0};
        String[] headers = {"One", "Two", "Three", "Four"};
        Integer[][] data = {oneRow, oneRow, oneRow, oneRow, oneRow,};
        final DefaultTableModel model = new DefaultTableModel(data, headers);
        final JTable table = new JTable(model);
        table.setDefaultRenderer(Object.class, new ProgressRenderer(0, maximum));
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        new Thread(new Runnable() {

            @Override
            public void run() {
                Object waiter = new Object();
                synchronized (waiter) {
                    int rows = model.getRowCount();
                    int columns = model.getColumnCount();
                    Random random = new Random(System.currentTimeMillis());
                    boolean done = false;
                    while (!done) {
                        int row = random.nextInt(rows);
                        int column = random.nextInt(columns);
                        Integer value = (Integer) model.getValueAt(row, column);
                        value++;
                        if (value <= maximum) {
                            model.setValueAt(value, row, column);
                            try {
                                waiter.wait(15);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        done = true;
                        for (row = 0; row < rows; row++) {
                            for (column = 0; column < columns; column++) {
                                if (!model.getValueAt(row, column).equals(maximum)) {
                                    done = false;
                                    break;
                                }
                            }
                            if (!done) {
                                break;
                            }
                        }
                    }
                    frame.setTitle("All work done");
                }
            }
        }).start();
    }

    public static class ProgressRenderer extends JProgressBar implements TableCellRenderer {

        private static final long serialVersionUID = 1L;

        public ProgressRenderer(int min, int max) {
            super(min, max);
            this.setStringPainted(true);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
            this.setValue((Integer) value);
            return this;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TableWithProgressBars().createGUI();
            }
        });

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM