JTextArea内容实时刷新,显示append()方法追加的内容

前情讨论:

最近在做一个Java GUI小程序,点击按钮(JButton)进行一些处理,然后在文本框(JTextArea)中输出相关信息

看过别人的讨论说,如果处理部分比较复杂且耗时,就会阻塞swing线程,导致swing线程中JTextArea组件对象的内容不能实时刷新:当处理部分的代码运行结束时,JTextArea的内容会一下子刷新。

也就是提示信息不是一条一条显示的,而是在界面卡一段时间之后,一下全部显示。建议另外开启线程来进行复杂的处理。


参考博客:

Java Swing 实时刷新JTextArea,以显示不断append的内容?  这里提到了三种方法,可以按实际情况选择

其中第三种方法的原博是:https://www.cnblogs.com/Forrest-Janny/p/6610759.html    (原博更详细一点,建议看原博)


方法一

1.使用JTextArea的paintImmediately方法

JTextArea继承了javax.swing.JComponent 的 paintImmediately 方法

paintImmediately方法原型

  • 调用JTextArea对象(这里是promptContent)的append方法,然后调用paintImmediately方法
//将info立即追加到JTextArea中
public static void appendJTextArea(String info) {
	promptContent.append(info+"\n");
	promptContent.paintImmediately(promptContent.getBounds()); 
}
  • paintImmediately的第二种定义
//将info立即追加到JTextArea中
public static void appendJTextArea(String info) {
	promptContent.append(info+"\n");
	promptContent.paintImmediately(promptContent.getX(), promptContent.getY(), promptContent.getWidth(), promptContent.getHeight()); 
}

需要追加信息时,调用编写的appendJTextArea方法即可。效果:可以实时追加。

我的问题:

因为我要追加的内容很多,所以将JTextArea放在了JScrollPane中,超出的部分可通过拖动垂直或水平的滑块观察到。

但仍然出现了问题:JTextArea矩形框大小内的信息是实时更新的,超出部分是在窗口卡住一段时间后,同时添加的。

修正:

还是需要将处理部分另起一个线程来完成,所有的内容都是实时显示的。可以自己编写开启新线程,也可以参考方法三中第1、3段代码。


方法二

使用Swing线程的SwingUtilities.invokeLater 来追加内容

public static void appendJTextArea(String info) {
	SwingUtilities.invokeLater(new Runnable() {
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			if(info != null) {
				promptContent.append(info+"\n");
			}
				
		}
	});
}

问题:

情况同方法一相同:需要将处理部分在新开启的线程中完成,可以自己编写,也可以参考方法三第1、3段代码


方法三

https://www.cnblogs.com/Forrest-Janny/p/6610759.html的思路是:JTextArea追加信息时开启一个线程,进行复杂处理时也开启一个线程,这样两个线程之间是不干涉的。

 

  • 先声明定义了java.util.concurrent.ExecutorService类一个变量service ,用来开启线程
static private ExecutorService service = Executors.newCachedThreadPool(new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "output");
        }
});

接下来就是,在追加信息方法中开启线程,在复杂处理处开启线程

  • 追加信息的代码
public static void appendJTextArea(String info) {
	service.submit(new Runnable() {
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			promptContent.append(info+"\n");
		}
	});
}
  • 处理部分的代码(我这里是点击某个按钮,开始进行相关处理)
//为startButton设置监听器
startButton.addActionListener(new ActionListener() {
			
	@Override
	public void actionPerformed(ActionEvent e) {				
		
		service.submit(new Runnable() {		
			@Override
			public void run() {
                            //这里写自己进行的处理
                        }
		});
				
	}//actionPerformed

});

效果总结:三种方法都可以实时追加信息


补充(我的情况)

处理过程:通过循环实现读取、解析多个文件,每个循环中需要输出多个提示信息,信息之间有一定逻辑联系,例如:打开了xx文件->成功提取了数据->成功存入数据库... 

使用方法三时出现了一点问题,它将两个临近的循环中的提示信息交替输出了,我的期望是相同文件的提示一起输出。

交叉输出例子:(同一文件的信息输出应该连着的,这里用相同颜色代表同一文件)

打开了aaa文件

提取了数据

打开了bbb文件

成功存入数据库

提取了数据

成功存入数据库

期望追加信息的效果是:

打开了aaa文件

成功提取了数据

成功存入数据库

打开了bbb文件

成功提取了数据

成功存入数据库

方法一,方法二是按我的预期输出的。

 

 

你可能感兴趣的:(Java)