gpt4 book ai didi

java - 我怎样才能让这个方法在我的循环中更新GUI?

转载 作者:行者123 更新时间:2023-12-01 16:54:32 24 4
gpt4 key购买 nike

我正在制作一个运行一些 cmd 命令(USMT 和文件传输)的程序

它工作正常,但我只在文本框中从 cmd 中获取最后一行,并且只有在它完成操作后才获取。我希望它实时打印 cmd 输出的内容。

 public void load() throws IOException {
ProcessBuilder builder = new ProcessBuilder(
"cmd.exe", "/c", "cd \"C:\\usmt\" && loadstate.bat");
builder.redirectErrorStream(true);
Process p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;

while (true) {

line = r.readLine();
if (line == null) { break; }

cOut.setText(line);
System.out.println(line);
}
}

最佳答案

原因...

问题的根本原因是您阻塞了事件调度线程,这会阻止 UI 在命令执行之后更新。

Swing 是一个单线程框架,这意味着您不应在 EDT 上下文中执行阻塞或长时间运行的代码。 Swing 也不是线程安全的,这意味着您永远不应该从 EDT 上下文之外修改 UI 的状态。

参见Concurrency in Swing了解更多详情

解决方案...

要解决这个问题,您有两个基本选择。您可以使用 Thread,但随后您需要负责确保 UI 的所有更新都同步到 EDT 的上下文,或者您可以使用 SwingWorker ,例如...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Runner {

public static void main(String[] args) {
new Runner();
}

public Runner() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private JTextArea ta;

public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(25, 80);
add(new JScrollPane(ta));

JButton execute = new JButton("Make it so");
execute.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
execute.setEnabled(false);
CommandWorker worker = new CommandWorker(ta, "cmd.exe", "/c", "cd \"C:\\usmt\" && loadstate.bat");
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case "state":
SwingWorker work = (SwingWorker) evt.getSource();
switch (worker.getState()) {
case DONE: {
try {
worker.get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();;
JOptionPane.showMessageDialog(TestPane.this, "Execution of command failed: " + ex.getMessage());
} finally {
execute.setEnabled(true);
}
}
break;
}
break;
}
}
});
worker.execute();
}
});

add(execute, BorderLayout.SOUTH);
}

}

public static class CommandWorker extends SwingWorker<List<String>, String> {

private JTextArea ta;
private List<String> commands;

public CommandWorker(JTextArea ta, List<String> commands) {
this.ta = ta;
this.commands = commands;
}

public CommandWorker(JTextArea ta, String... commands) {
this(ta, Arrays.asList(commands));
}

@Override
protected List<String> doInBackground() throws Exception {
List<String> output = new ArrayList<>(25);
ProcessBuilder builder = new ProcessBuilder(commands);
builder.redirectErrorStream(true);

Process p = builder.start();
try (BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line = null;
while ((line = r.readLine()) != null) {
output.add(line);
publish(line);
}
}
return output;
}

@Override
protected void process(List<String> chunks) {
for (String text : chunks) {
ta.append(text);
ta.append("\n");
}
}

}

}

查看 Worker Threads and SwingWorker了解更多详情

关于java - 我怎样才能让这个方法在我的循环中更新GUI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34858405/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com