JTextArea内容实时刷新,显示append()方法追加的内容,亲测解决在多线程中paintImmediately()和scrollBar()使用的坑
1、处理部分比较复杂且耗时,阻塞swing线程,导致swing线程中JTextArea组件对象的内容不能实时刷新:当处理部分的代码运行结束时,JTextArea的内容会一下子刷新。2、追加的内容过多,将JTextArea放在了JScrollPane中,超出的部分可通过拖动垂直或水平的滑块观察到。提示信息不是一条一条显示的,而是在界面卡一段时间之后,一下全部显示。建议另外开启线程来进行复杂的处理。J
·
如果你有以下GUI界面文本框输出的问题,都能在下面找到答案(亲测)。
1、处理部分比较复杂且耗时,阻塞swing线程,导致swing线程中JTextArea组件对象的内容不能实时刷新:当处理部分的代码运行结束时,JTextArea的内容会一下子刷新。
现象问题:
提示信息不是一条一条显示的,而是在界面卡一段时间之后,一下全部显示。建议另外开启线程来进行复杂的处理。
(核心处理:处理和显示部分直接放到同一个线程中,单独append()即可。)
2、追加的内容过多,将JTextArea放在了JScrollPane中,超出的部分可通过拖动垂直或水平的滑块观察到。
出现问题:
JTextArea矩形框大小内的信息是实时更新的,超出部分是在窗口卡住一段时间后,同时添加的。
3、在开启多线程打印、使用paintImmediately()立刻渲染和scrollBar()没达到效果
的情况下。
完整测试程序如下:
package org.example;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class JscollTest extends JFrame{
private JButton jButton1; //选择文件按钮
private JButton jButton2; //开始访问按钮
private JTextArea showResult; //底层文本框显示区
private JScrollPane scrollPane;
private JScrollBar scrollBar;
public JscollTest(String title){
this.setTitle(title);
this.setSize(550, 500);//设置窗体大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //关闭事件触发
this.setLocationRelativeTo(null); //窗口初始化定位
this.setLayout(null); //组件绝对定位
//jButton1点击开启非线程打印日志
jButton1 = new JButton("非线程打印");
jButton1.setFont(new Font("宋体", Font.PLAIN, 18));
jButton1.setBounds(50, 30, 150, 70);
//jButton2点击开启线程打印日志
jButton2 = new JButton("线程打印");
jButton2.setFont(new Font("宋体", Font.PLAIN, 20));
jButton2.setBounds(350, 30, 150, 70);
//showResult为打印输出框JTextArea
showResult = new JTextArea();
showResult.setFont(new Font( "宋体",Font.PLAIN,14));
showResult.setMargin( new Insets( 5 , 5 , 5 , 5 ));
showResult.setEditable(false);
//* 设置编辑框为滚动面板 *//
scrollPane = new JScrollPane(showResult);
scrollPane.setBounds(20, 190, 500, 220);
add(scrollPane);
add(jButton1);
add(jButton2);
setVisible(true); //使界面可视化
setResizable(false); //固定界面的大小
//将按钮加入监听器监听事件。
MyClickListener listener = new MyClickListener();
jButton1.addActionListener(listener);
jButton2.addActionListener(listener);
/**
* 在构造函数中的进行主线程的打印
*
*测试其他两种按钮点击情况时最好先关闭mainTreadPrint
* */
// mainTreadPrint();//仅是文本框内打印效果
}
/**
* 放在构造函数中,加载程序时直接主线程开启打印。
* */
public void mainTreadPrint() {
scrollBar = scrollPane.getVerticalScrollBar();
for (int i = 0; i <= 1000000; i++) {
showResult.append("你好呀,mainTreadPrint!\n" + i);
/**
* 注意:主线程中的打印直接JTextArea的append函数,GUI界面就能够正常显示
*此时paintImmediately()和scrollBar.setValue()加不加都不影响效果
*
* */
//showResult.paintImmediately(showResult.getBounds());//开启立即打印
//scrollBar.setValue(scrollBar.getMaximum());//每次滚动至最后一条数据
}
}
/**
*点击按钮1,开启非线程下日志打印。
* */
public void nullThreadPrint() {
for (int i = 0; i <= 1000000; i++) {
/**
* 注意:点击事件jButton1开启非线程打印,GUI界面都不会正常显示,两种显示效果
* 第一种:
* 仅仅append()追加数据,界面完全卡主,之后一次打印
*
* 第二种:
* 仅仅添加showResult.paintImmediately(showResult.getBounds());
* 页面打印也是实时打印出来,但只会实时打印一页,然后页面卡住,滚轮卡住,最后一次性打印
*原因:showResult.getBounds()超范围,空指针异常
*
* 第三种:
* 添加showResult.paintImmediately(showResult.getBounds());
* 添加scrollBar.setValue(scrollBar.getMaximum());
*其实也是直接报空指针异常,表现就是卡死。
* Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
* */
showResult.append("你好呀,nullThreadPrint!\n" + i);
/* showResult.paintImmediately(showResult.getBounds());
scrollBar.setValue(scrollBar.getMaximum());//拉到最后一行*/
jButton2.setEnabled(true);
}
}
/**
*点击按钮2,开启线程下日志打印。
* */
public void ThreadPrint () {
/**
* 这里只是打印功能,如果是比较耗时的计算,有文章讲,数据处理用一个线程,数据打印用一个线程
* (亲测没必要,只要区别于主线程,计算和打印同时放在一个多线程中即可)
* */
for (int i = 0; i <= 1000000; i++) {
/**
* 这里开启多线程的打印,效果与在主线程中执行
* 特别不一致!!!!
* 主线程中append()追加就能够正常显示,而主线程中添加
* showResult.paintImmediately(showResult.getBounds());
* scrollBar.setValue(scrollBar.getMaximum());//拉到最后一行
* 也是可以正常显示的。
*
*但是在非主线程中,即使开启了多线程,单独地append()追加,GUI界面正常显示!
* 一旦同时添加了
* showResult.paintImmediately(showResult.getBounds());
* scrollBar.setValue(scrollBar.getMaximum());
*直接行完毕报空指针异常!!!!!。
*
* 单独添加showResult.paintImmediately(showResult.getBounds());
* GUI界面反复刷新,界面显示稀碎!!!!
*
* 单独添加scrollBar.setValue(scrollBar.getMaximum());
* 还是直接报java.lang.NullPointerException
* */
showResult.append("你好呀,ThreadPrint!\n" + i);
//showResult.paintImmediately(showResult.getBounds());
//scrollBar.setValue(scrollBar.getMaximum());//拉到最后一行
jButton2.setEnabled(true);
}
}
/**
* 实现ActionListener监听方法,进行对两个按钮的事件监听
* */
private class MyClickListener implements ActionListener{
private int value = 0;
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == jButton1) {value = 1;}
else if(e.getSource() == jButton2) {value = 2;}
switch (value) {
case 1:
showResult.setText("");
jButton1.setEnabled(false);
nullThreadPrint(); //Buttton1点击,开始不开启线程打印*/
break;
case 2:
//这里不包裹一个线程,点击按钮2就先会卡住,像按钮1一样
new Thread(()-> {
try {
showResult.setText("");
jButton2.setEnabled(false);
ThreadPrint(); //Button2点击,开始进行线程打印(或者是别的功能中存在打印,同样适用)
} catch (Exception ex) {
ex.printStackTrace();
}
}).start();
break;
}
}
}
public static void main(String[] args) {
new JscollTest("日志输出");
}
}
更多推荐
已为社区贡献7条内容
所有评论(0)