简体   繁体   English

批处理文件运行时显示不确定的 JProgressBar

[英]Display indeterminate JProgressBar while batch file runs

I've been browsing SO and google for a while now for an answer to this question, but I can't seem to find one that really works.我一直在浏览 SO 和 google 一段时间来寻找这个问题的答案,但我似乎找不到真正有效的答案。 I'll start from the beginning:我将从头开始:

I created a Java class with a method that runs a batch file in the background (the command window does not appear).我使用在后台运行批处理文件的方法创建了一个 Java 类(不出现命令窗口)。 The program works great, except that it would be a little confusing to the end user, since the batch file takes a while to complete--the user will not know if the program is still running or not.该程序运行良好,除了它会让最终用户有点困惑,因为批处理文件需要一段时间才能完成——用户将不知道程序是否仍在运行。 After the batch script finishes executing, a message dialog appears saying it's finished, but for the period of time between when the method is run and the dialog appears, it looks as if the program is doing nothing.批处理脚本完成执行后,会出现一个消息对话框,说明它已完成,但在方法运行和对话框出现之间的时间段内,程序看起来好像什么都不做。

So here's my question: I would very much like to display a new frame with a text area that shows the output of the batch file.所以这是我的问题:我非常想显示一个带有显示批处理文件输出的文本区域的新框架。 However, I understand that this is very difficult to do without creating temporary files, writing to them, reading from them, and so on.但是,我知道如果不创建临时文件、写入它们、读取它们等等,这是非常困难的。 I would rather avoid that if possible.如果可能的话,我宁愿避免这种情况。 Therefore, I have decided it might be better to display an indeterminate JProgressBar while the process is running, and close it when the process is finished.因此,我决定最好在进程运行时显示一个不确定的 JProgressBar,并在进程完成时关闭它。 Unfortunately, I don't think Swing can handle this since it would require running multiple processes at once.不幸的是,我认为 Swing 无法处理这个问题,因为它需要同时运行多个进程。 I have heard of a SwingWorker but am not exactly sure how that would be used in this case.我听说过 SwingWorker,但不确定在这种情况下如何使用它。 I have the following SSCCE, which works, but does not have the progress bar implemented.我有以下 SSCCE,它有效,但没有实现进度条。

public myClass(){
    public static void main(String[] args){
        String[] commands = {"cmd.exe", "/C", "C:\\users\\....\\myBat.bat"};
        Process p = Runtime.getRuntime().exec(commands);
        p.waitFor()
        JOptionPane.showMessageDialog(null, "Process finished!");
    }
}

While p.waitFor() waits for the process, there is nothing on the screen.当 p.waitFor() 等待进程时,屏幕上什么也没有。 I just want something showing the user that a process is still running.我只是想要一些东西向用户展示一个进程仍在运行。 Thoughts?想法? Thanks!谢谢!

You can run a ProcessBuilder in the background of a SwingWorker , as shown below, to get both output and a progress bar.您可以运行ProcessBuilder在背景SwingWorker ,如下图所示,得到两个输出和一个进度条。

图片

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.*;

/**
 * @se http://stackoverflow.com/a/20603012/230513
 * @see http://stackoverflow.com/a/17763395/230513
 */
public class SwingWorkerExample {

    private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER);
    private final JTextArea textArea = new JTextArea(20, 20);
    private JButton startButton = new JButton("Start");
    private JButton stopButton = new JButton("Stop");
    private JProgressBar bar = new JProgressBar();
    private BackgroundTask backgroundTask;
    private final ActionListener buttonActions = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            JButton source = (JButton) ae.getSource();
            if (source == startButton) {
                textArea.setText(null);
                startButton.setEnabled(false);
                stopButton.setEnabled(true);
                backgroundTask = new BackgroundTask();
                backgroundTask.execute();
                bar.setIndeterminate(true);
            } else if (source == stopButton) {
                backgroundTask.cancel(true);
                backgroundTask.done();
            }
        }
    };

    private void displayGUI() {
        JFrame frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setBorder(
            BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panel.setLayout(new BorderLayout(5, 5));

        JScrollPane sp = new JScrollPane();
        sp.setBorder(BorderFactory.createTitledBorder("Output: "));
        sp.setViewportView(textArea);

        startButton.addActionListener(buttonActions);
        stopButton.setEnabled(false);
        stopButton.addActionListener(buttonActions);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(startButton);
        buttonPanel.add(stopButton);
        buttonPanel.add(bar);

        panel.add(statusLabel, BorderLayout.PAGE_START);
        panel.add(sp, BorderLayout.CENTER);
        panel.add(buttonPanel, BorderLayout.PAGE_END);

        frame.setContentPane(panel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private class BackgroundTask extends SwingWorker<Integer, String> {

        private int status;

        public BackgroundTask() {
            statusLabel.setText((this.getState()).toString());
        }

        @Override
        protected Integer doInBackground() {
            try {
                ProcessBuilder pb = new ProcessBuilder("ls", "-lR", "/");
                pb.redirectErrorStream(true);
                Process p = pb.start();
                String s;
                BufferedReader stdout = new BufferedReader(
                    new InputStreamReader(p.getInputStream()));
                while ((s = stdout.readLine()) != null && !isCancelled()) {
                    publish(s);
                }
                if (!isCancelled()) {
                    status = p.waitFor();
                }
                p.getInputStream().close();
                p.getOutputStream().close();
                p.getErrorStream().close();
                p.destroy();
            } catch (IOException | InterruptedException ex) {
                ex.printStackTrace(System.err);
            }
            return status;
        }

        @Override
        protected void process(java.util.List<String> messages) {
            statusLabel.setText((this.getState()).toString());
            for (String message : messages) {
                textArea.append(message + "\n");
            }
        }

        @Override
        protected void done() {
            statusLabel.setText((this.getState()).toString() + " " + status);
            stopButton.setEnabled(false);
            startButton.setEnabled(true);
            bar.setIndeterminate(false);
        }

    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SwingWorkerExample().displayGUI();
            }
        });
    }
}

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

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