我一直在尝试使用自定义输出流在Jtext区域上显示可执行文件的输出。
可执行文件是通过按钮从调用的
try {
Process p = Runtime.getRuntime().exec("cgminer.exe" + " -o " + Infos.Address + ":" + Infos.Port + " -u " + Infos.User + " -p " + Infos.Password);
p.waitFor();
String line;
BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while((line = error.readLine()) != null){
System.out.println(line);
}
error.close();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line=input.readLine()) != null){
System.out.println(line);
}
input.close();
OutputStream outputStream = p.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
printStream.println();
printStream.flush();
printStream.close();
}
catch (Exception e) {
// ...
}
}
}
然后将输出定向到jtext
public class CustomOutputStream extends OutputStream {
private JTextArea textArea;
public CustomOutputStream(JTextArea textArea) {
this.textArea = textArea;
}
@Override
public void write(int b) throws IOException {
textArea.append(String.valueOf((char) b));
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}
我的问题是,当我调用第一个类时,按钮将锁定,并且没有输出使其到达jtext。只有当我强制关闭cgminer时,输出才会出现。
真的很感激任何帮助,因为这使我的大脑产生了扭曲。
最佳答案
我的问题是,当我调用第一个类时,按钮将锁定,并且没有输出使其到达jtext。只有当我强制关闭cgminer时,输出才会出现。
这是捆绑Swing事件线程的经典症状。当您在Swing事件线程(也称为EDT或事件调度线程)上运行长时间运行的代码时,您将阻止该线程执行繁琐的工作,包括绘制GUI并与用户进行交互,从而有效地“冻结”了GUI。
解决方案不是像其他建议那样注释waitFor()
,而是在后台线程(例如SwingWorker)中运行它和任何其他阻塞代码。执行此操作时,请确保仅在事件线程上更新Swing GUI。 SwingWorker具有通过其发布和处理方法执行此操作的内置方法。
有关详细信息,请查看Concurrency in Swing
您还需要执行更多线程处理,因为代码的某些行正在阻塞,并且将阻止下游的行运行,直到它们解除阻塞为止,但是到那时所有重要的操作都已完成。例如,这些块:
// this blocks
p.waitFor();
// this blocks both times you use it
while((line = error.readLine()) != null){
System.out.println(line);
}