前言
事件调度线程 ,此线程在后台运行。
通常Swing不是线程安全的,除非另行说明,否则所有Swing组件及其相关类都必须保证在同一个线程(事件调度线程)中进行访问。
AWT中有一个先进先出的事件队列(EventQueue)单例,添加到该队列中的任务(Runnable)将按顺序逐一同一线程中被执行,该线程称为事件调度线程。
新建一个线程显示进度条。
一、My_EventQueue事件调度线程
//通常Swing不是线程安全的,除非另行说明,否则所有Swing组件及其相关类都必须保证在同一个线程(事件调度线程)中进行访问
//AWT中有一个先进先出的事件队列(EventQueue)单例,添加到该队列中的任务(Runnable)将按顺序逐一同一线程中被执行,该线程称为事件调度线程
//Swing组件也延用了该队列实例,所有Swing组件的创建/修改/绘制/响应输入都必须要添加到该事件队列中执行,组件注册的各种监听器,回调方法也是被添加到事件队列中执行,
//即,所有监听器的回调方法中就处于事件调度线程,可以直接操作UI
//添加任务到事件调度线程:
//EventQueue.invokeLater(Runnable doRun);或者SwingUtilities.invokeLater(Runnable doRun);
//上面两者的区别:EventQueue在AWT包中,SwingUtilities在Swing包中,后者内部实际上是直接又调用了前者
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
//import java.awt.EventQueue;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import javax.swing.JOptionPane;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JProgressBar; //进度条
public class My_SwingUtilities implements Runnable{
public static JProgressBar progressbar; //创建进度条
public static void main(String[] args) {
//EventQueue.invokeLater(
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
//此处处于事件调度线程
createGUI();
}
});
My_SwingUtilities my = new My_SwingUtilities(); //类实例
new Thread(my).start(); //进度条线程开始
}
//此处处于事件调度线程
public static void createGUI() {
JFrame My_Frame = new JFrame("事件调度线程");
My_Frame.setSize(300,400);//设置窗口大小
My_Frame.setLocationRelativeTo(null);//设置窗口相对于指定组件的位置,null表示在中间
My_Frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭窗口时关闭程序
progressbar = new JProgressBar(); //创建进度条
progressbar.setStringPainted(true); //显示当前进度条信息
progressbar.setBorderPainted(false); //设置进度条边框不显示
progressbar.setForeground(new Color(0, 210, 40)); //设置进度条的前景色
progressbar.setBackground(new Color(188, 190, 194)); //设置进度条的背景颜色
JPanel My_panel = new JPanel(new BorderLayout());//面板
JButton My_button = new JButton("按钮");
final JLabel My_label = new JLabel("正在下载: 0%");//标签
final JTextArea textArea = new JTextArea();//文本域
//添加面板滚动条
JScrollPane scrollpane = new JScrollPane(textArea);
scrollpane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);//垂直滚动条显示
scrollpane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);//横轴滚动条不显示
My_panel.add(scrollpane, BorderLayout.CENTER);
My_panel.add(My_button, BorderLayout.SOUTH);
My_panel.add(progressbar, BorderLayout.SOUTH);
My_panel.add(My_label, BorderLayout.NORTH);
//按钮添加监听事件
My_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//此处处于事件调度线程(所有监听器的回调都在事件调度线程中回调
My_Frame.setTitle("liyangwei");//按钮按下时改变窗口标题
}
});
My_Frame.setContentPane(My_panel);//窗口添加面板
My_Frame.setVisible(true);//设置窗口为可见
//创建后台任务
//<String, Integer>
//String是后台计算结果的类型,即SwingWorker的doInBackground()和get()方法返回的结果类型
//Integer是用于保存此SwingWorker的publish()和process()方法的中间结果的类型
SwingWorker<String, Integer> task = new SwingWorker<String, Integer>(){
protected String doInBackground() throws Exception{
for (int i = 0; i < 100; i++) {
//线程延时
Thread.sleep(5000);
//设置进度条的值
//progressbar.setValue(i);
//设置progress属性的值(通过属性改变监听器传递数据到事件调度线程)
setProgress(i);
//通过SwingWorker内部机制传递数据到事件调度线程
publish(i);
}
//返回计算结果
return "下载完成";
}
//此方法在调用doInBackground函数调用publish(i)方法后在事件调度线程中被回调)
protected void process(List<Integer> chunks) {
Integer progressValue = chunks.get(0);
textArea.append("已下载:" + progressValue + "%\n");
}
//此方法将在后台任务完成后在事件调度线程中被回调
protected void done() {
String result = null;
try {
//获取计算结果
result = get();
} catch (Exception e) {
e.printStackTrace();
}
My_label.setText(result);
textArea.append(result);
}
};
//添加属性改变监听器,当doInBackground函数调用setProgress(i)方法改变progress的值后在事件调度线程中被调回
task.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
Object progressValue = evt.getNewValue();
My_label.setText("正在下载:" + progressValue + "%");
}
}
});
//启动任务
task.execute();
}
//另一种方法,创建一个线程运行进度条
public void run() {
for(int i = 0; i < 100; i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//设置进度条的值
progressbar.setValue(i);
}
JOptionPane.showMessageDialog(null, "加载完成");
}
}
二、注意
下面这段程序是创建一个运行的线程,用来设置进度条的值。
此线程用来区分事件调度线程的后台线程,可以没有这段代码,但要在事件调度线程中设置进度条的值。
//另一种方法,创建一个线程运行进度条
public void run() {
for(int i = 0; i < 100; i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//设置进度条的值
progressbar.setValue(i);
}
JOptionPane.showMessageDialog(null, "加载完成");
}
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。