带有用于数据库数据插入的线程的jProgressBar

时间:2017-06-29 16:04:09

标签: java multithreading swing progress-bar

我正在尝试实现JprogressBar来显示数据插入进度。 基本上,用户选择将数据源导入数据库的数量。 使用此参数,主程序启动一个列出这些参数的方法,并使用foreach循环调用插入线程和ProgressBar更新线程。

connect-distributed.sh

线程有点自己工作,但结果不是我想要的,导致数据被导入并且进度条正在更新,但是在导入所有数据后它正在更新到100%。只要导入线程完成每个(Maquina i)对象的导入,我就需要更新进度条。

如果有必要,我可以提供线程代码......但我不知道这种调用方法是否可以提供我想要的结果。在论坛上搜索我发现了一些关于EDT的东西,我认为这个问题没有被更新。你能帮助我解决这个问题吗?

最小和可验证的例子: 我的代码很短。 netbeans生成的代码是巨大的,sry为此。

该代码模拟了我的问题。只有在for循环结束后才会刷新窗口。但是BarraDeProgresso线程和SysOut一样运行一些信息......

for (Maquina i : m.listar()) {
    //Passing to Import Thread the object with the data and a Date parameter
    ImportarDados imp = new ImportarDados(i, jDateInicial.getDate());

    //Calling progress bar update Thread with the progressbar itself and progress parameter
    BarraDeProgresso bp = new BarraDeProgresso(progresso, progImportacao);

    imp.run();
    bp.run();
}

组件初始化(Netbeans生成)

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLabel;
import javax.swing.JProgressBar;



public class Minimo extends javax.swing.JFrame {


   public Minimo() {
       initComponents();
   }

   private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
       int progImportacao[] = {0};

       progresso.setMaximum(15);
       for (int i = 0; i <= 15; i++) {
           ImportarDados imp = new ImportarDados(i,lblProgresso);
           BarraDeProgresso bp = new BarraDeProgresso(progresso, progImportacao);

           imp.run();
           bp.run();

           progImportacao[0] += 1;
       }
   } 

可运行的课程

private void initComponents() {

    progresso = new javax.swing.JProgressBar();
    lblProgresso = new javax.swing.JLabel();
    jButton1 = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    lblProgresso.setText("...");

    jButton1.setText("IMPORT DATA");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(60, 60, 60)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(lblProgresso)
                .addComponent(progresso, javax.swing.GroupLayout.PREFERRED_SIZE, 382, javax.swing.GroupLayout.PREFERRED_SIZE))
            .addContainerGap(47, Short.MAX_VALUE))
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(jButton1)
            .addGap(191, 191, 191))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addGap(32, 32, 32)
            .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 29, Short.MAX_VALUE)
            .addComponent(lblProgresso)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(progresso, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(37, 37, 37))
    );

    pack();
}// </editor-fold>

Main(Netbeans Generated)

class BarraDeProgresso implements Runnable {

    public JProgressBar jProgressBar1;
    public int progresso[];

    public BarraDeProgresso(JProgressBar barra, int progresso[]) {
        this.jProgressBar1 = barra;
        this.progresso = progresso;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(0);
            System.out.println("TBARRA PROG " + progresso[0]);
            jProgressBar1.setValue(progresso[0]);
            jProgressBar1.repaint();
        } catch (InterruptedException e) {
        }

    }
}

class ImportarDados implements Runnable {

    private int pi = 0;
    JLabel x;

    public ImportarDados(int i, JLabel tag) {
        this.pi = i;
        this.x = tag;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(500);

            x.setText(Integer.toString(pi)+" /15");

        } catch (InterruptedException ex) {
            Logger.getLogger(Minimo.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
} 

1 个答案:

答案 0 :(得分:1)

您当前的代码不会创建后台线程。是的,你有Runnables,但你在它们上面调用了run(),这意味着你在Swing事件线程上调用它们。执行此操作时,您将阻止事件线程,从而有效地冻结您的程序。相反,你需要:

  • 通过将Runnable传递给Thread对象的构造函数并在该Thread上调用start()来创建一个真正的后台线程。
  • 不会在这些后台线程中改变Swing组件
  • 或按照Lesson: Concurrency in Swing使用SwingWorker,这将有助于解决上述问题的

有关使用SwingWorker的示例,请参阅:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;

@SuppressWarnings("serial")
public class Minimo2 extends JPanel {
    private static final int EB_GAP = 15;
    private static final int PROG_BAR_WDTH = 400;
    public static final int MAX_DATA = 15;
    private JProgressBar progresso;
    private JLabel lblProgresso;
    private JButton jButton1;
    private Action importDataAction = new ImportDataAction("Import Data");

    public Minimo2() {
        initComponents();
    }

    private void initComponents() {
        progresso = new JProgressBar(0, MAX_DATA);
        lblProgresso = new JLabel(" ");
        jButton1 = new JButton(importDataAction);
        int progBarHeight = progresso.getPreferredSize().height;
        progresso.setPreferredSize(new Dimension(PROG_BAR_WDTH, progBarHeight));
        progresso.setStringPainted(true);

        JPanel btnPanel = new JPanel();
        btnPanel.add(jButton1);
        JPanel labelPanel = new JPanel();
        labelPanel.add(lblProgresso);
        JPanel progressPanel = new JPanel();
        progressPanel.add(progresso);

        setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(btnPanel);
        add(Box.createVerticalStrut(EB_GAP));
        add(labelPanel);
        add(Box.createVerticalStrut(EB_GAP));
        add(progressPanel);
    }

    private class ImportDataAction extends AbstractAction {
        public ImportDataAction(String name) {
            super(name); // give the button text
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic); // give it a hot key
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setEnabled(false); // disable our button
            ImportDataWorker worker = new ImportDataWorker(MAX_DATA);
            worker.addPropertyChangeListener(new WorkerListener());
            worker.execute();
        }
    }

    private class WorkerListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if ("progress".equals(evt.getPropertyName())) {
                int progValue = (int) evt.getNewValue();
                progresso.setValue(progValue);
                String text = String.format("%02d/15", progValue);
                lblProgresso.setText(text);
            } else if ("state".equals(evt.getPropertyName())) {
                if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
                    @SuppressWarnings("rawtypes")
                    SwingWorker worker = (SwingWorker)evt.getSource();
                    try {
                        worker.get();
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                    progresso.setValue(MAX_DATA);
                    String text = String.format("%02d/15", MAX_DATA);
                    lblProgresso.setText(text);
                    importDataAction.setEnabled(true);
                }
            }
        }
    }

    private class ImportDataWorker extends SwingWorker<Void, Void> {

        private static final long SLEEP_TIME = 500;
        private int max;

        public ImportDataWorker(int max) {
            this.max = max;
        }

        @Override
        protected Void doInBackground() throws Exception {
            for (int i = 0; i < max; i++) {                
                setProgress(i);
                Thread.sleep(SLEEP_TIME);
            }
            return null;
        }

    }

    private static void createAndShowGui() {
        Minimo2 mainPanel = new Minimo2();

        JFrame frame = new JFrame("Minimo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}