Java 在执行长程序期间,作为控制台输出动态更新JTextArea?
假设一个程序执行大量的方法。例如,在安装软件安装方法时,您希望跟踪JtextArea中的进度。我正在执行一个需要20秒或更长时间才能执行的程序。我想在文本区域中显示输出,更新间隔为50到100毫秒。我如何实现它? 我使用了计时器,但它在程序执行后更新了文本区域,而不是在执行期间,java线程冻结了GUIJava 在执行长程序期间,作为控制台输出动态更新JTextArea?,java,swing,Java,Swing,假设一个程序执行大量的方法。例如,在安装软件安装方法时,您希望跟踪JtextArea中的进度。我正在执行一个需要20秒或更长时间才能执行的程序。我想在文本区域中显示输出,更新间隔为50到100毫秒。我如何实现它? 我使用了计时器,但它在程序执行后更新了文本区域,而不是在执行期间,java线程冻结了GUI temp1.redirectOutput( textArea ); final int i = 0; Timer timer = new Timer(1000, new A
temp1.redirectOutput( textArea );
final int i = 0;
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
String str = "";
int i = 0;
while(i < 3000){
str = "aaaa";
System.out.println(str);
i++;
}
System.out.println( new java.util.Date().toString() );
System.err.println( System.currentTimeMillis() );
}
});
timer.start();
temp1.重定向输出(textArea);
最终积分i=0;
计时器计时器=新计时器(1000,新ActionListener(){
已执行的公共无效操作(操作事件e){
字符串str=“”;
int i=0;
而(i<3000){
str=“aaaa”;
系统输出打印项次(str);
i++;
}
System.out.println(新java.util.Date().toString());
System.err.println(System.currentTimeMillis());
}
});
timer.start();
使用SwingWorker
获取您可能缓存到可管理块中的信息,并使用worker发布这些信息
请查看以了解更多详细信息
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.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
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 Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 implements LongTimeConsumer {
private JTextArea ta;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
JButton btn = new JButton("Start");
add(btn, BorderLayout.SOUTH);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
btn.setEnabled(false);
LongTimeWorker worker = new LongTimeWorker(TestPane.this);
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
LongTimeWorker worker = (LongTimeWorker) evt.getSource();
if ("state".equals(evt.getPropertyName())) {
btn.setEnabled(worker.isDone());
}
}
});
worker.execute();
}
});
}
@Override
public void contentUpdated(List<String> values) {
for (String text : values) {
ta.append(text);
ta.append("\n");
}
ta.setCaretPosition(ta.getDocument().getLength());
}
}
public interface LongTimeConsumer {
public void contentUpdated(List<String> values);
}
public class LongTimeWorker extends SwingWorker<List<String>, List<String>> {
private LongTimeConsumer consumer;
public LongTimeWorker(LongTimeConsumer consumer) {
this.consumer = consumer;
}
@Override
protected List<String> doInBackground() throws Exception {
List<String> total = new ArrayList<>(1000);
List<String> values = new ArrayList<>(100);
for (int index = 0; index < 1000; index++) {
values.add("Some more text " + index);
if (index % 100 == 0) {
total.addAll(values);
publish(values);
values = new ArrayList<>(100);
}
Thread.sleep(1);
}
if (!values.isEmpty()) {
total.addAll(values);
publish(values);
}
return total;
}
@Override
protected void process(List<List<String>> chunks) {
for (List<String> values : chunks) {
consumer.contentUpdated(values);
}
}
}
}
导入java.awt.BorderLayout;
导入java.awt.EventQueue;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.SwingWorker;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展JPanel实现LongTimeConsumer{
私人住宅区;
公共测试窗格(){
setLayout(新的BorderLayout());
ta=新的JTextArea(10,20);
添加(新的JScrollPane(ta));
JButton btn=新JButton(“开始”);
添加(btn,BorderLayout.SOUTH);
btn.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
btn.setEnabled(false);
LongTimeWorker=新的LongTimeWorker(TestPane.this);
worker.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
LongTimeWorker=(LongTimeWorker)evt.getSource();
if(“state”.equals(evt.getPropertyName())){
btn.setEnabled(worker.isDone());
}
}
});
worker.execute();
}
});
}
@凌驾
已更新公共void内容(列表值){
用于(字符串文本:值){
ta.追加(文本);
ta.追加(“\n”);
}
ta.setCaretPosition(ta.getDocument().getLength());
}
}
公共接口长期消费者{
更新的公共无效内容(列表值);
}
公共类LongTimeWorker扩展SwingWorker{
私人长期消费者;
公共长期工作者(长期消费者){
这个。消费者=消费者;
}
@凌驾
受保护列表doInBackground()引发异常{
列表总数=新阵列列表(1000);
列表值=新的ArrayList(100);
对于(int-index=0;index<1000;index++){
添加(“更多文本”+索引);
如果(索引%100==0){
总计.addAll(值);
出版(价值观);
值=新的ArrayList(100);
}
睡眠(1);
}
如果(!values.isEmpty()){
总计.addAll(值);
出版(价值观);
}
返回总数;
}
@凌驾
受保护的无效进程(列表块){
for(列表值:块){
消费者。内容更新(价值);
}
}
}
}
如果您使用的是
System.out
,您也可以执行类似或的操作。您可以在此处看到完整的代码。使用.append(String str)
方法如何?@AndriyRymar这是最简单的方法。不,那不行,明白了。当我遇到同样的问题时,我只是使用了一些结构,比如List
或StringBuilder
,并在那里管理所有新行。然后,当我必须在UI上显示日志数据时,我只需将JTextArea
中的内容替换为我的结构的最新内容,而使用SwingWorker