packagecom.siwuxie095.swingworker;
importjava.awt.BorderLayout;
importjava.awt.EventQueue;
importjava.awt.event.MouseAdapter;
importjava.awt.event.MouseEvent;
importjava.io.BufferedReader;
importjava.io.InputStreamReader;
importjava.net.URL;
importjava.net.URLConnection;
importjava.util.List;
importjava.util.concurrent.ExecutionException;
importjavax.swing.JButton;
importjavax.swing.JFrame;
importjavax.swing.JPanel;
importjavax.swing.JScrollPane;
importjavax.swing.JTextArea;
importjavax.swing.SwingWorker;
importjavax.swing.UIManager;
importjavax.swing.UnsupportedLookAndFeelException;
importjavax.swing.border.EmptyBorder;
importcom.sun.java.swing.plaf.windows.WindowsLookAndFeel;
public classTestSwingWorker extendsJFrame {
privateJPanel contentPane;
privateJTextArea textArea;
/**
* Launch the application.
*/
public staticvoidmain(String[] args) {
EventQueue.invokeLater(newRunnable() {
publicvoidrun() {
try{
TestSwingWorker frame = newTestSwingWorker();
frame.setVisible(true);
} catch(Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
publicTestSwingWorker() {
try{
UIManager.setLookAndFeel(newWindowsLookAndFeel());
} catch(UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = newJPanel();
contentPane.setBorder(newEmptyBorder(5, 5, 5, 5));
contentPane.setLayout(newBorderLayout(0, 0));
setContentPane(contentPane);
JButton btnRun = newJButton("Run");
btnRun.setFocusable(false);
btnRun.addMouseListener(newMouseAdapter() {
@Override
publicvoidmouseClicked(MouseEvent e) {
//鼠标点击Run按钮后执行读取网络数据的方法
webRead();
}
});
contentPane.add(btnRun, BorderLayout.NORTH);
JScrollPane scrollPane = newJScrollPane();
contentPane.add(scrollPane, BorderLayout.CENTER);
textArea = newJTextArea();
scrollPane.setViewportView(textArea);
}
publicvoidwebRead() {
/**
*创建一个SwingWorker,SwingWorker是一个专门为界面而实现的线程类,
*它可以非常方便的在当前的UI线程中执行一定的耗时操作,且可以很安全
*的将它的返回值发送给UI线程
*
*创建SwingWorker时,需要指定两个泛型:
*第一个泛型是SwingWorker线程执行之后得到的结果的类型(返回值的类型)
*第二个泛型是SwingWorker线程执行中间所发布(publish)的数据的类型
*
*这里将整个SwingWorker的返回值定义为StringBuilder,中间发布的数据定义为String
*
*覆盖三个方法:doInBackground()、process()、done()
*
* doInBackground()中执行耗时的操作,如:读取网络数据、读取本地文件、等待
* doInBackground()产生的中间数据publish()到process()中
* doInBackground()的返回值在done()中被get()到
*
*即两种方法都能获取最终的结果
*
*最后调用SwingWorker的execute()方法执行该线程
*/
newSwingWorker() {
//后台处理过程
@Override
protectedStringBuilder doInBackground() throwsException {
//创建一个URL对象,用于读取网络数据
//指定网址:http://www.apache.org
URL url=newURL("http://www.apache.org");
//使用openConnection()方法获取一个互联网连接
//返回值是URLConnection类型,创建以接收返回值
URLConnection connection=url.openConnection();
//将读取的输入流getInputStream()层层包装,最后使用BufferedReader来读取网络数据
//先包装成InputStreamReader,并指定字符集,再包装成BufferedReader
BufferedReader reader=newBufferedReader(
newInputStreamReader(connection.getInputStream(),"UTF-8"));
//读取每一行数据
String line;
StringBuilder builder=newStringBuilder();
while((line=reader.readLine())!=null) {
//SwingWorker线程并不属于UI线程,
//所以不能在doInBackground()方法中为UI元素设定属性
//可以将当前的数据传递(发布)给process(),这就是中间的数据
//publish(line);
//也可以将line添加到builder中,一次性刷新到UI界面,
//而不像上面的publish()每读取一行就刷新到UI界面
builder.append(line).append("\n");
}
//关闭流
reader.close();
returnbuilder;
}
@Override
protectedvoidprocess(List chunks) {
//process()方法被执行后,其中的内容会自动分发给UI线程
//process()中的所有操作都是线程安全的
//
//使用for循环来接收传入的值(即中间的数据,String类型)
//从传入的List中获取一行数据(取出数据)
for(String line : chunks) {
//添加到textArea并换行
textArea.append(line);
textArea.append("\n");
}
super.process(chunks);
}
//由于每读取一行数据都要让UI线程来执行一次刷新的工作,
//这对于UI线程来说工作量还是比较大的
//可以将网页全部读取后,让这些数据一次性刷新到UI界面上,
//不过这样,等待的时间会更长
@Override
protectedvoiddone() {
//可以在done()方法为UI元素设定属性
//done()中的所有操作都是线程安全的
try{
//get()返回StringBuilder类型
//有异常抛出,用try catch捕获
textArea.setText(get().toString());
} catch(InterruptedException e) {
e.printStackTrace();
} catch(ExecutionException e) {
e.printStackTrace();
}
super.done();
}
}.execute();
}
}