事件调度线程与进度条

前言

事件调度线程 ,此线程在后台运行。
通常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提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值