Fork me on GitHub

使用SwingWorker为界面执行异步任务

------------------siwuxie095

   

   

   

   

   

   

   

工程名:TestSwingWorker

包名:com.siwuxie095.swingworker

类名:TestSwingWorker.java

   

   

工程结构目录如下:

   

   

   

   

   

代码:

   

package com.siwuxie095.swingworker;

   

import java.awt.BorderLayout;

import java.awt.EventQueue;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.net.URL;

import java.net.URLConnection;

import java.util.List;

import java.util.concurrent.ExecutionException;

   

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;

import javax.swing.border.EmptyBorder;

   

import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;

   

public class TestSwingWorker extends JFrame {

   

private JPanel contentPane;

private JTextArea textArea;

   

/**

* Launch the application.

*/

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {

public void run() {

try {

TestSwingWorker frame = new TestSwingWorker();

frame.setVisible(true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

   

/**

* Create the frame.

*/

public TestSwingWorker() {

 

try {

UIManager.setLookAndFeel(new WindowsLookAndFeel());

} catch (UnsupportedLookAndFeelException e1) {

e1.printStackTrace();

}

 

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setBounds(100, 100, 450, 300);

contentPane = new JPanel();

contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

contentPane.setLayout(new BorderLayout(0, 0));

setContentPane(contentPane);

 

JButton btnRun = new JButton("Run");

btnRun.setFocusable(false);

btnRun.addMouseListener(new MouseAdapter() {

@Override

public void mouseClicked(MouseEvent e) {

//鼠标点击Run按钮后执行读取网络数据的方法

webRead();

}

});

contentPane.add(btnRun, BorderLayout.NORTH);

 

JScrollPane scrollPane = new JScrollPane();

contentPane.add(scrollPane, BorderLayout.CENTER);

 

textArea = new JTextArea();

scrollPane.setViewportView(textArea);

}

 

 

public void webRead() {

 

/**

* 创建一个SwingWorkerSwingWorker是一个专门为界面而实现的线程类,

* 它可以非常方便的在当前的UI线程中执行一定的耗时操作,且可以很安全

* 的将它的返回值发送给UI线程

*

* 创建SwingWorker时,需要指定两个泛型:

* 第一个泛型是SwingWorker线程执行之后得到的结果的类型(返回值的类型)

* 第二个泛型是SwingWorker线程执行中间所发布(publish)的数据的类型

*

* 这里将整个SwingWorker的返回值定义为StringBuilder,中间发布的数据定义为String

*

* 覆盖三个方法:doInBackground()process()done()

*

* doInBackground() 中执行耗时的操作,如:读取网络数据、读取本地文件、等待

* doInBackground() 产生的中间数据 publish() process()

* doInBackground() 的返回值在 done() 中被 get()

*

* 即两种方法都能获取最终的结果

*

* 最后调用SwingWorker execute() 方法执行该线程

*/

new SwingWorker<StringBuilder, String>() {

 

 

//后台处理过程

@Override

protected StringBuilder doInBackground() throws Exception {

//创建一个URL对象,用于读取网络数据

//指定网址:http://www.apache.org

URL url=new URL("http://www.apache.org");

 

//使用 openConnection() 方法获取一个互联网连接

//返回值是URLConnection类型,创建以接收返回值

URLConnection connection=url.openConnection();

 

//将读取的输入流 getInputStream() 层层包装,最后使用 BufferedReader 来读取网络数据

//先包装成 InputStreamReader,并指定字符集,再包装成 BufferedReader

BufferedReader reader=new BufferedReader(

new InputStreamReader(connection.getInputStream(),"UTF-8"));

 

//读取每一行数据

String line;

StringBuilder builder=new StringBuilder();

while ((line=reader.readLine())!=null) {

//SwingWorker线程并不属于UI线程,

//所以不能在 doInBackground() 方法中为UI元素设定属性

//可以将当前的数据传递(发布)给 process(),这就是中间的数据

//publish(line);

 

 

//也可以将 line 添加到builder中,一次性刷新到UI界面,

//而不像上面的 publish() 每读取一行就刷新到UI界面

builder.append(line).append("\n");

}

 

//关闭流

reader.close();

 

return builder;

}

 

@Override

protected void process(List<String> 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

protected void done() {

//可以在 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();

}

   

}

   

   

   

将窗体 JFrame 的 LookAndFeel 设定为 Windows

   

   

在根面板 contentPane 的上方添加一个 JButton,

中间添加一个 JScrollPane

   

   

将 JButton 的文本(text)改为 Run,并 Rename 为 btnRun,

将 focusable 属性设为 false

   

   

在 JScrollPane 的 Viewport 添加一个 JTextArea

   

   

为 JButton 添加 mouseClicked 事件,鼠标单击 Run 按钮后,

读取 Apache官网 的 HTML 数据

   

Apache官网:http://www.apache.org

   

   

   

SwingWorker 线程中的 3 个方法:

   

1)doInBackground()

   

   

   

2)process()

   

   

   

(3)done()

   

   

   

   

   

运行程序:

   

   

   

   

   

关于 SwingWorker 参考链接:

参考链接1参考链接2参考链接3参考链接4

   

   

   

   

   

   

【made by siwuxie095】

posted on 2017-04-06 16:39  siwuxie095  阅读(3541)  评论(0编辑  收藏  举报

导航