【问题标题】:JProgressBar does not update inside actionPerformed - Java SwingJProgressBar 不会在 actionPerformed 内部更新 - Java Swing
【发布时间】:2019-09-27 01:04:11
【问题描述】:

我创建了一个 Swing 应用程序。我正在使用 JProgressBar 来显示进度,并且我希望在按钮处理程序(ActionListener.actionPerformed)内执行某些任务时更改进度,但它不起作用。代码如下:

package com.capgemini.skillparser.ui;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;

import com.capgemini.skillparser.domain.Employee;
import com.capgemini.skillparser.excel.impl.SkillsXlsxReader;
import com.capgemini.skillparser.excel.impl.SkillsXlsxWriter;
import com.capgemini.skillparser.text.impl.EmployeeNumbersTextReader;

public class TelaPrincipal extends JFrame {

    private JPanel contentPane;
    private JTextField textField;
    private JTextField textField_1;
    private JTextField textField_2;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    TelaPrincipal frame = new TelaPrincipal();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public TelaPrincipal() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 427);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel label = new JLabel(
                new ImageIcon(
                        new ImageIcon(getClass().getClassLoader().getResource("capgemini-logo.jpg"))
                        .getImage().getScaledInstance(300, 100, Image.SCALE_DEFAULT)
                )
        );
        label.setBounds(10, 11, 414, 73);
        contentPane.add(label);     

        textField = new JTextField();
        textField.setBackground(Color.LIGHT_GRAY);
        textField.setBounds(10, 113, 414, 20);
        contentPane.add(textField);
        textField.setColumns(10);

        JButton btnSelecionarPlanilha = new JButton("Selecionar planilha");
        btnSelecionarPlanilha.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                FileNameExtensionFilter filter = new FileNameExtensionFilter("*.xlsx", "xlsx");
                j.setFileFilter(filter);
                int r = j.showSaveDialog(null); 

                if (r == JFileChooser.APPROVE_OPTION) { 
                    textField.setText(j.getSelectedFile().getAbsolutePath()); 
                }
            }
        });
        btnSelecionarPlanilha.setBounds(10, 144, 217, 23);
        contentPane.add(btnSelecionarPlanilha);

        textField_1 = new JTextField();
        textField_1.setBackground(Color.LIGHT_GRAY);
        textField_1.setBounds(10, 178, 414, 20);
        contentPane.add(textField_1);
        textField_1.setColumns(10);

        JButton btnSelecionarArquivoTxtfiltro = new JButton("Selecionar arquivo txt (filtro)");
        btnSelecionarArquivoTxtfiltro.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                FileNameExtensionFilter filter = new FileNameExtensionFilter("*.txt", "txt");
                j.setFileFilter(filter);
                int r = j.showSaveDialog(null); 

                if (r == JFileChooser.APPROVE_OPTION) { 
                    textField_1.setText(j.getSelectedFile().getAbsolutePath()); 
                }
            }
        });
        btnSelecionarArquivoTxtfiltro.setBounds(10, 209, 217, 23);
        contentPane.add(btnSelecionarArquivoTxtfiltro);

        textField_2 = new JTextField();
        textField_2.setBackground(Color.LIGHT_GRAY);
        textField_2.setBounds(10, 243, 414, 20);
        contentPane.add(textField_2);
        textField_2.setColumns(10);

        JButton btnSelecionarDestino = new JButton("Selecionar destino");
        btnSelecionarDestino.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                j.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int r = j.showSaveDialog(null); 

                if (r == JFileChooser.APPROVE_OPTION) { 
                    textField_2.setText(j.getSelectedFile().getAbsolutePath()); 
                }               
            }
        });
        btnSelecionarDestino.setBounds(10, 274, 217, 23);
        contentPane.add(btnSelecionarDestino);

        JProgressBar progressBar = new JProgressBar();
        progressBar.setBounds(10, 318, 414, 23);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        contentPane.add(progressBar);

        JButton btnGerarPlanilhaAjustada = new JButton("Gerar Planilha Ajustada");
        btnGerarPlanilhaAjustada.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

//---------------PROBLEM HERE---------------------------------------
                try {

                    progressBar.setIndeterminate(true);
                    progressBar.setValue(30);

//read a xlsx file

                    progressBar.setValue(50);

//write a xlsx file

                    progressBar.setValue(100);

                    progressBar.setIndeterminate(false);
//nothing above related to progressBar works properly, these statements only execute after the button handler code finishes

                }catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
        btnGerarPlanilhaAjustada.setBounds(101, 354, 230, 23);
        contentPane.add(btnGerarPlanilhaAjustada);
    }
}

我尝试了许多替代代码,但没有任何效果。有些地方建议使用多线程方法,但我不知道如何构造我的代码以以一种很好的方式使用多线程。我在这个意义上的所有尝试都失败了。

有人可以帮帮我吗?谢谢

【问题讨论】:

标签: java swing


【解决方案1】:

读取和写入是“繁重”的操作,可能需要一些时间才能完成。这就是为什么您必须在后台执行它们,否则 GUI 线程,也就是 Event Dispatch Thread 将很忙,因此事件将无法发生(gui 将冻结)。

您必须创建一个SwingWorker。整个想法是这样的:

  1. 按钮被点击
  2. SwingWorker 启动
  3. Worker 在后台执行繁重操作的一部分
  4. Worker 将进度条值发布到 GUI 线程
  5. 重复 3 & 4
  6. 工作人员已完成。

在您的代码中查看我的示例(代码中的 cmets):

public class TelaPrincipal extends JFrame {
    private SwingWorker<Void, Integer> worker;
    private JPanel contentPane;
    private JTextField textField;
    private JTextField textField_1;
    private JTextField textField_2;
    private JProgressBar progressBar;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            TelaPrincipal frame = new TelaPrincipal();
            frame.setVisible(true);
        });
    }

    /**
     * Create the frame.
     */
    public TelaPrincipal() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 427);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel label = new JLabel();
        label.setBounds(10, 11, 414, 73);
        contentPane.add(label);

        textField = new JTextField();
        textField.setBackground(Color.LIGHT_GRAY);
        textField.setBounds(10, 113, 414, 20);
        contentPane.add(textField);
        textField.setColumns(10);

        JButton btnSelecionarPlanilha = new JButton("Selecionar planilha");
        btnSelecionarPlanilha.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                FileNameExtensionFilter filter = new FileNameExtensionFilter("*.xlsx", "xlsx");
                j.setFileFilter(filter);
                int r = j.showSaveDialog(null);

                if (r == JFileChooser.APPROVE_OPTION) {
                    textField.setText(j.getSelectedFile().getAbsolutePath());
                }
            }
        });
        btnSelecionarPlanilha.setBounds(10, 144, 217, 23);
        contentPane.add(btnSelecionarPlanilha);

        textField_1 = new JTextField();
        textField_1.setBackground(Color.LIGHT_GRAY);
        textField_1.setBounds(10, 178, 414, 20);
        contentPane.add(textField_1);
        textField_1.setColumns(10);

        JButton btnSelecionarArquivoTxtfiltro = new JButton("Selecionar arquivo txt (filtro)");
        btnSelecionarArquivoTxtfiltro.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                FileNameExtensionFilter filter = new FileNameExtensionFilter("*.txt", "txt");
                j.setFileFilter(filter);
                int r = j.showSaveDialog(null);

                if (r == JFileChooser.APPROVE_OPTION) {
                    textField_1.setText(j.getSelectedFile().getAbsolutePath());
                }
            }
        });
        btnSelecionarArquivoTxtfiltro.setBounds(10, 209, 217, 23);
        contentPane.add(btnSelecionarArquivoTxtfiltro);

        textField_2 = new JTextField();
        textField_2.setBackground(Color.LIGHT_GRAY);
        textField_2.setBounds(10, 243, 414, 20);
        contentPane.add(textField_2);
        textField_2.setColumns(10);

        JButton btnSelecionarDestino = new JButton("Selecionar destino");
        btnSelecionarDestino.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser j = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
                j.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int r = j.showSaveDialog(null);

                if (r == JFileChooser.APPROVE_OPTION) {
                    textField_2.setText(j.getSelectedFile().getAbsolutePath());
                }
            }
        });
        btnSelecionarDestino.setBounds(10, 274, 217, 23);
        contentPane.add(btnSelecionarDestino);

        progressBar = new JProgressBar();
        progressBar.setBounds(10, 318, 414, 23);
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        contentPane.add(progressBar);

        JButton btnGerarPlanilhaAjustada = new JButton("Gerar Planilha Ajustada");
        btnGerarPlanilhaAjustada.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!worker.isDone())
                    worker.cancel(true); //destroy previous worker
                initWorker();
                worker.execute();
            }
        });
        btnGerarPlanilhaAjustada.setBounds(101, 354, 230, 23);
        contentPane.add(btnGerarPlanilhaAjustada);
        initWorker();
    }

    private void initWorker() {
        worker = new SwingWorker<Void, Integer>() {
            @Override
            protected void process(List<Integer> chunks) {
                int value = chunks.get(0);
                progressBar.setValue(value);
            }

            @Override
            protected Void doInBackground() throws Exception {
                publish(10); //progress bar value that will be sent to process() method
                Thread.sleep(2000); //assume read file takes 2 seconds
                publish(50); //progress bar value that will be sent to process() method
                Thread.sleep(2000); //assume another bg operation takes 2 secs
                publish(99);
                return null;
            }

        };
    }
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多