当制作UI界面时候遇到了一个问题:
当按钮触发时,执行函数
BtnEvent(){ //Swing的按钮触发函数
//通过Swing TextArea显示输出--TextArea.append()
A();//执行时间很快,执行完毕后输出"A执行完毕"
B(); //执行时间很长,执行完后输出"B执行完毕"
}
我希望得到的是A()执行完后的消息输出,马上显示在UI的TextArea上,可以最终结果是,只有等BtnEvent()里的两个函数同时完毕,才会在UI里显示消息,并且是一并显示,而不是像控制台system.out.println()那样,一行一行滚动输出。
为了解决这个问题,java swing 有一个类 SwingWorker。在里面可以通过匿名内部类的方式,重写两个方法。
// 运行实践长的代码放里面执行,消息可以用publish()函数发布
@Override
doInBackground()
//chunks 收集了publish()收集的消息,然后在process里用TextArea.append输出UI消息
@Override
process(List<String> chunks)
同时,为了不成堆的输出消息,而是滚动连贯的输出消息,可以创建一个全局变量数组(ArrayList<String> msgList)存储消息,并且设置两个线程,一个主线程运行程序,一个用来监视消息的变化。
以下是效果
以下是实例代码
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
public class GuiTestYH extends JFrame {
private JTextArea textArea;
private JButton button;
//创建一个
private ArrayList<String> msgList = new ArrayList<String>();
public GuiTestYH() {
super("Swing Example");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setLocationRelativeTo(null);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
add(panel);
textArea = new JTextArea();
panel.add(textArea, BorderLayout.CENTER);
button = new JButton("Test");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//SwingWorker类将主线程放在后台运行
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
Thread threadA = new Thread(new Runnable() {
public void run() {
while (true) {
// 每1秒检查一次MsgList是否有变化
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int size = msgList.size();
if (size > 0) {
for (int i = 0; i < msgList.size(); i++) {
publish("New value: " + msgList.get(i));
}
msgList.clear();
}
}
}
});
threadA.start();
Test();
threadA.join();
// TODO Auto-generated method stub
return null;
}
@Override
protected void process(List<String> chunks) {
for (String string : chunks) {
textArea.append(string);
}
}
};
worker.execute();
}
});
panel.add(button, BorderLayout.SOUTH);
}
public void Test() throws Exception {
Logger logger = MyLogger.getLogger();
Handler hd =new Handler() {
//匿名内部类中重写publish
//该hander的作用是,当logger被添加消息时,publish就会被触发,利用record.getMessage()获取
//新增的消息
@Override
public void publish(LogRecord record) {
msgList.add(record.getMessage());
}
@Override
public void flush() {
// TODO Auto-generated method stub
}
@Override
public void close() throws SecurityException {
// TODO Auto-generated method stub
}
};
logger.addHandler(hd);
// 加入数据
for (int i = 0; i < 20; i++) {
Thread.sleep(1000);
logger.info("数据 : "+i+"\r\n");
}
}
public static void main(String[] args) {
GuiTestYH frame = new GuiTestYH();
frame.setVisible(true);
}
}