我正在将文件导入到项目中,一旦用户单击选择此文件,我会执行一些操作,其中包括通过命令行执行的操作。等待后台进程以不同类别的SwingWorker结束
我已经使用这个方法来完成它:
p = Runtime.getRuntime().exec(command, null, new File(directory));
p.waitFor();
由于这一过程可能需要一些时间,我决定把显示新帧当前进程的所有输出一个进度条弹出。我遵循@trashgod的this代码适应了我的项目。为了这个问题的目的,让我们说我完全按照它的样子。
我只想让这个窗口在命令运行时出现,然后关闭它自己。我可以通过从override override方法中放置框架来完成此操作。
我的问题是,我从其他类创建这个类,而这是正在执行它继续与代码。例如:
method1();
method2();
new SwingWorkerExample().displayGUI(); //Process continues in background
method3();
这里我的方法3()在SwingWorkerExample类的过程完成之前正在执行。我怎么能解决这个问题?
我已经试图把在displayGUI方法本月底:
while(!backgroundTask.isDone()){
//do nothing
}
但它使整个框架无法正常工作或可能冻结它。 我也试着写了使p在backgrandtask类的全局变量后的方法:
public Process getProcess(){
return p;
}
然后从displaGUI调用()以下:
backgroundTask.getProcess().waitFor();
但它返回一个空指针异常。
我还能做些什么来等待显示命令窗口的输出时结束进程?
谢谢。 更新: 下面是链接代码的副本,其中包含一些更改以显示我的意思。我不希望打印的第二个文本,直到处理完毕:
package mcve;
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 https://stackoverflow.com/a/20603012/230513
* @see https://stackoverflow.com/a/17763395/230513
* @seehttps://stackoverflow.com/questions/20600721/
*/
public class SwingWorkerExample {
private JFrame frame;
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() {
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("ping", "-c", "5","google.com");//change -c for -n in windows
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);
frame.dispose();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Here I start");
new SwingWorkerExample().displayGUI();
System.out.println("I'll show up when the SwingWorkerExample has finnished");
}
});
}
UPDATE2:我也试图把在main方法(displayGUI)的过程,并发送至一个参考过程,但它不工作,窗口只是冻结,并没有显示出来:
frame.setVisible(true);
bar.setIndeterminate(true);
try {
ProcessBuilder pb = new ProcessBuilder("ping", "-c", "20", "google.com");
pb.redirectErrorStream(true);
Process p;
p = pb.start();
backgroundTask = new BackgroundTask(p);
backgroundTask.execute();
p.waitFor();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace(System.err);
}
更新3:继Eals答案我有这样结束了,仍然没有按的@Hovercraft全” t如预期的那样工作,因为字符串在过程结束之前出现。也许我的理解是错误的或者它只是没有在这方面的工作:
package mcve;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import static javax.swing.Action.MNEMONIC_KEY;
public class SwingWorkerExample {
private JFrame frame;
private ExecuteFrame backgroundTask;
private class properyListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// the above percolates from the SwingWorker to the containing
// JPanel
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
int processState = backgroundTask.getProcessStatus();
System.out.println("Process State: " + processState + "\n");
}
}
}
private void displayGUI() {
frame = new JFrame("Swing Worker Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
backgroundTask = new ExecuteFrame();
frame.add(backgroundTask);
backgroundTask.addPropertyChangeListener(new properyListener());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
backgroundTask.startProcess();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
System.out.println("Here I start");
SwingUtilities.invokeLater(() -> new SwingWorkerExample().displayGUI());
System.out.println("I'll show up when the SwingWorkerExample has finnished");
}
});
}
}
@SuppressWarnings("serial")
class ExecuteFrame extends JPanel {
private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER);
private final JTextArea textArea = new JTextArea(20, 30);
private StartAction startAction = new StartAction("Start", KeyEvent.VK_S);
private StopAction stopAction = new StopAction("Stop", KeyEvent.VK_T);
private JProgressBar bar = new JProgressBar();
private BackgroundTask backgroundTask;
private int processStatus;
public ExecuteFrame() {
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
textArea.setFocusable(false);
JScrollPane sp = new JScrollPane();
sp.setBorder(BorderFactory.createTitledBorder("Output: "));
sp.setViewportView(textArea);
stopAction.setEnabled(false);
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(startAction));
buttonPanel.add(new JButton(stopAction));
buttonPanel.add(bar);
add(statusLabel, BorderLayout.PAGE_START);
add(sp, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
public void startProcess() {
if (backgroundTask != null && !backgroundTask.isDone()) {
return; // background task not yet done
}
textArea.setText("");
startAction.setEnabled(false);
stopAction.setEnabled(true);
backgroundTask = new BackgroundTask();
backgroundTask.addPropertyChangeListener(new BGTaskListener());
backgroundTask.execute();
bar.setIndeterminate(true);
}
public void cancelProcess() {
if (backgroundTask != null && !backgroundTask.isDone()) {
backgroundTask.cancel(true);
}
}
public void processStopped() {
statusLabel.setText((backgroundTask.getState()).toString() + " "
+ processStatus);
stopAction.setEnabled(false);
startAction.setEnabled(true);
bar.setIndeterminate(false);
// Window thisWindow = SwingUtilities.getWindowAncestor(textArea);
// thisWindow.dispose();
}
public int getProcessStatus() {
return processStatus;
}
public class BGTaskListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
processStopped();
}
// percolate this listener up to the main JPanel's Prop Chng
// Listener
ExecuteFrame.this.firePropertyChange(evt.getPropertyName(), evt.getOldValue(),
evt.getNewValue());
}
}
private class BackgroundTask extends SwingWorker<Integer, String> {
@Override
protected Integer doInBackground() throws Exception {
List<String> list = new ArrayList<>();
list.add("ping");
String name = System.getProperty("os.name");
if (name.startsWith("Win")) {
list.add("-n");
} else {
list.add("-c");
}
list.add("5");
list.add("google.com");
try {
ProcessBuilder pb = new ProcessBuilder(list);
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()) {
processStatus = p.waitFor();
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.destroy();
} catch (IOException | InterruptedException ex) {
ex.printStackTrace(System.err);
}
return processStatus;
}
@Override
protected void process(java.util.List<String> messages) {
statusLabel.setText((this.getState()).toString());
for (String message : messages) {
textArea.append(message + "\n");
}
}
}
private class StartAction extends AbstractAction {
public StartAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
startProcess();
}
}
private class StopAction extends AbstractAction {
public StopAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
cancelProcess();
}
}
}
输出是:
Here I start
I'll show up when the SwingWorkerExample has finnished
Process State: 0
相反的:
Here I start
Process State: 0
I'll show up when the SwingWorkerExample has finnished
你好@Hovercraft,谢谢你的回答。显示输出已经由链接中提供的代码完成。我不明白你如何告诉代码在其他地方等待。我的意思是,你调用myworker.execute(),然后继续使用那个方法。你如何等待(SwingWorker.StateValue.DONE == evt.getNewValue())下的代码被执行? – nck
@nck:你不告诉代码“等待”,而是这是事件驱动的编程 - 你响应**事件**,这里事件是SwingWorker正在完成。如果您仍不确定要做什么,请考虑通过发布有效且体面的[mcve]来澄清您的问题和代码,这是一个小型可编译和可运行的演示程序,可以帮助我们了解您的问题。也许在这个MCVE中,使用Thread.sleep来模拟你的后台进程。 –
我刚刚添加了代码副本,显示我的意思,我不希望在ping完成之前打印第二个字符串。 – nck