概述
我有将系统输出重定向到jtext区域的代码,但是直到代码运行完毕,该jtextarea才会更新。 如何在运行时实时修改代码以实时更新jtextarea?
private void updateTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
consoleTextAreaInner.append(text);
}
});
}
private void redirectSystemStreams() {
OutputStream out = new OutputStream() {
@Override
public void write(int b) throws IOException {
updateTextArea(String.valueOf((char) b));
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
updateTextArea(new String(b, off, len));
}
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setOut(new PrintStream(out, true));
System.setErr(new PrintStream(out, true));
}
其余代码主要只是一个按钮的动作侦听器:
private void updateButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String shopRoot = this.shopRootDirTxtField.getText();
String updZipPath = this.updateZipTextField.getText();
this.mainUpdater = new ShopUpdater(new File(shopRoot), updZipPath);
this.mainUpdater.update();
}
该update()方法开始在文件系统上复制+粘贴文件的过程,在此过程中,使用system.out.println提供有关程序当前所在位置的最新状态,以参考有多少文件 它必须复制。
也许调用object(textare)repaint()方法?
举个例子
很难百分百肯定地说出出了什么问题,因为我们没有看到很多关键的相关代码,但是很有可能会遇到Swing线程问题。 您需要在后台线程中读取流,然后在Swing事件线程EDT上调用对文本区域的更新方法。 否则,您将在等待流读取的同时绑定EDT,从而完全冻结GUI。 SwingWorker会很好地工作。 考虑在每次遇到新行时发布到JTextArea。
例如:
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class MyRedirectStream {
private JTextArea textArea;
public MyRedirectStream(JTextArea gui) {
this.textArea = gui;
}
public void redirect() {
System.setOut(new PrintStream(new MyOutStream(), true));
System.setErr(new PrintStream(new MyOutStream(), true));
}
private class MyOutStream extends OutputStream {
private static final int MAX_LENGTH = 1600;
private StringBuilder sb = new StringBuilder(MAX_LENGTH + 100);
@Override
public void write(int b) throws IOException {
sb.append((char)b);
if (sb.length() > MAX_LENGTH) {
sendToTextArea(sb.toString());
sb = new StringBuilder();
}
}
@Override
public void flush() throws IOException {
sendToTextArea(sb.toString());
sb = new StringBuilder();
super.flush();
}
private void sendToTextArea(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textArea.append(text);
}
});
}
}
}
和:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class StreamToTextArea2 {
public static void main(String[] args) {
final TextPanel gui = new TextPanel();
final MyRedirectStream myRedirectStream = new MyRedirectStream(
gui.getTextarea());
myRedirectStream.redirect();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame("Redirect");
JButton showTextBtn = new JButton(new AbstractAction("Show Text") {
@Override
public void actionPerformed(ActionEvent arg0) {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
gui.clearText();
final File file = fileChooser.getSelectedFile();
new Thread(new Runnable() {
public void run() {
try {
Scanner scan = new Scanner(file);
while (scan.hasNextLine()) {
System.out.println(scan.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}).start();
}
}
});
JButton clearTextBtn = new JButton(
new AbstractAction("Clear Text") {
@Override
public void actionPerformed(ActionEvent e) {
gui.clearText();
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(clearTextBtn);
btnPanel.add(showTextBtn);
frame.getContentPane().add(gui);
frame.getContentPane().add(btnPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
class TextPanel extends JPanel {
private JTextArea textarea = new JTextArea(20, 40);
public TextPanel() {
setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(textarea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
public JTextArea getTextarea() {
return textarea;
}
public void clearText() {
textarea.setText("");
}
}
+1,对新的Runnable()感到好奇,您是否知道它将被缓存还是在每次读取字节时生成线程?
@arynaq:不,不会被缓存。这段代码不是很有效。最好建立一个缓冲区或StringBuilder,然后在缓冲区足够大时批处理数据。
@arynaq:现在它将被缓存一些。
@HovercraftFullOfEels我似乎无法导入TextPanel以及随后的.getTextArea()和.clearText()是TextPanel错误还是应该将其视为J软件包之一的一部分?在您的所有代码中,这些是唯一无法识别的显示。我已经安装了所有JGoodies库,并且正在使用IntelliJ Idea作为我的iDE。提前致谢。
@dbconfession:对不起,被遗漏了。
@HovercraftFullOfEelsahh好的,我现在看到它。谢谢。
@dbconfession:我添加了您正在询问的缺少的类TextPanel。
@HovercraftFullOfEels我不认为您的代码解决了OP的问题。这是他的问题的一个很好的例子。 Hes询问如何使控制台信息实时附加到JTextArea。您的代码获取文本文件的上下文,并将所有内容立即吐出到jTextArea。如果我理解正确的话,就像控制台显示正在发生的信息一样,JTextArea也应该实时显示,而不是仅仅一次转储控制台输出的最终结果。
您确实编写了invokeLater,并且稍后会调用它。 除非您执行一些有效的操作来使延迟确定,否则延迟的延迟是不确定的。 例如,您可以在文件之间插入Thread.sleep调用。
最后
以上就是典雅指甲油为你收集整理的java中的outputarea_关于多线程:Java将系统输出重定向到jtextarea,直到计算完成才更新...的全部内容,希望文章能够帮你解决java中的outputarea_关于多线程:Java将系统输出重定向到jtextarea,直到计算完成才更新...所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复