Swing208长任务

该博客展示了如何使用Java Swing库创建一个带有进度条的长任务应用,例如复制文件。通过`CopyTask`线程处理文件复制,并在`WaitDialog`对话框中实时更新进度。代码中详细解释了各个组件的功能和交互方式,包括按钮监听、事件处理、进度更新等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

长任务,显示进度条

在这里插入图片描述

package my;

import java.awt.Container;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Swing2
{
	private static void createGUI()
	{
		// JFrame指一个窗口,构造方法的参数为窗口标题
		// 语法:因为MyFrame是JFrame的子类,所以可以这么写
		JFrame frame = new MyFrame("Swing Demo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		// 设置窗口的其他参数,如窗口大小
		frame.setSize(500, 300);
		
		// 显示窗口
		frame.setVisible(true);
		
		
	}
	
	public static void main(String[] args)
	{
		// 此段代码间接地调用了 createGUI(),具体原理在 Swing高级篇 里讲解
		// 初学者先照抄此代码框架即可
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				createGUI();
			}
		});

	}
}

package my;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class MyFrame extends JFrame
{
	JButton okButton = new JButton("开始");
	WaitDialog waitDialog = null;
	
	public MyFrame(String title)
	{
		super(title);

		// Content Pane
		JPanel root = new JPanel();
		this.setContentPane(root);
		root.setLayout(new FlowLayout());

		root.add(okButton);
		
		okButton.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e)
			{				
				onMouseClicked();				
			}			
		});
	}

	// 按钮点击事件处理
	private void onMouseClicked()
	{			
		// 创建任务
		// 注意:在Win10下不允许直接在根目录下创建文件,所以建一个子目录来测试
		File srcFile = new File("C:/Users/Administrator/Desktop/1.zip");
		File dstFile = new File("C:/Users/Administrator/Desktop/2.zip");
		CopyTask th = new CopyTask();
		th.execute(srcFile, dstFile);	

		// 提示等待对话框
		waitDialog = new WaitDialog(this);
		waitDialog.exec();
	}
	
	private class CopyTask extends Thread
	{
		private File srcFile, dstFile;
			
		// 传入参数,并启动线程
		public void execute(File srcFile, File dstFile)
		{
			this.srcFile = srcFile;
			this.dstFile = dstFile;
			start(); // 启动线程
		}
		
		@Override
		public void run()
		{
			// 处理任务
			try {
				doInBackground();
			}catch(Exception e)
			{
				e.printStackTrace();
			}
			
			// 歇息 片刻
			try { sleep(100); }catch(Exception e) {}
			
			// 显示结果 ( 更新 UI )
			SwingUtilities.invokeLater( ()->{
				done();
			});
		}
		
		// 处理任务
		protected void doInBackground() throws Exception
		{
			InputStream inputStream = null;
			OutputStream outputStream = null;
			long lastTime = System.currentTimeMillis();;
			long fileSize = srcFile.length(); // 文件大小
			long count = 0; // 已经完成的字节数
			
			try {
				inputStream = new FileInputStream(srcFile);
				outputStream = new FileOutputStream(dstFile);
				byte[] buf = new byte[8192]; // 每次最多读取8KB
				while(true)
				{
					int n = inputStream.read(buf); // 从源文件读取数据
					if(n <= 0) break; // 已经读完
					outputStream.write(buf,  0,  n); // 写入到目标文件
					
					// 计数及显示进度
					count += n; // 已经拷贝完成的字节数
					long now = System.currentTimeMillis();
					if(now - lastTime > 500) // 每500毫秒更新一次进度
					{
						lastTime = now;
						updateProgress(count , fileSize);
						Thread.sleep(5000); // 不要老是占用CPU
					}
				}
			}
			finally {
				// 出异常时,确保所有的文件句柄被关闭
				try { inputStream.close();}catch(Exception e) {}
				try { outputStream.close();} catch(Exception e) {}
			}
		}
		
		// 更新进度
		protected void updateProgress(long count, long total)
		{
			SwingUtilities.invokeLater( ()->{
				if(waitDialog!=null)
				{
					// 设置进度条的进度(0-100)
					int percent = (int)(100 * count / total) ;
					waitDialog.setProgress( percent );
				}				
			});			
		}
		
		// 任务完成后,更新界面显示
		protected void done()
		{
			// 关闭对话框
			if(waitDialog!=null)
			{
				waitDialog.setVisible(false);
				waitDialog = null;
			}
		}
	}
	
	
}

package my;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;

import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

/* 提示等待对话框
 * 
 * 无标题栏 setUndecorated(true)
 * 
 * 对话框里没有任何关闭按钮,所以用户不能手工关闭,只能等待操作结束
 * 
 */
public class WaitDialog extends JDialog
{
	public JLabel display = new JLabel("请等待...");
	public JProgressBar pbar =  new JProgressBar(); // 进度条控件,用于显示进度
	
	public WaitDialog(JFrame owner)
	{
		super(owner, "", true);
		
		// 去掉标题栏
		this.setUndecorated(true);
		
		// 布局
		JPanel root = new JPanel();
		this.setContentPane(root);
		root.setLayout(new BorderLayout());
		
		// 背景
		root.setOpaque(true);
		root.setBackground(new Color(0xF4F4F4));
		
		Border b1 = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
		Border b2 = BorderFactory.createEmptyBorder(4, 4, 4, 4);
		Border b3 = BorderFactory.createCompoundBorder(b1, b2);
		root.setBorder(b3);
		
		// 文字提示
		display.setHorizontalAlignment(SwingConstants.CENTER);
		root.add(display, BorderLayout.CENTER);
		
		// 进度条 (0-100)
		pbar.setMinimum(0);  // 最小值
		pbar.setMaximum(100); // 最大值
		pbar.setPreferredSize(new Dimension(0,20)); // 高度设为20
		root.add(pbar, BorderLayout.PAGE_END);
		
		// 设置大小
		this.setSize(200, 80);
		
	}

	// 设置进度 (0-100)
	public void setProgress(int n)
	{
		pbar.setValue(n);
	}
	
	public void exec()
	{
		// 相对owner居中显示
		Rectangle frmRect = this.getOwner().getBounds();
		int width = this.getWidth();
		int height = this.getHeight();
		int x = frmRect.x + (frmRect.width - width) / 2;
		int y = frmRect.y + (frmRect.height - height) / 2;
		this.setBounds(x, y, width, height);

		// 显示窗口 ( 阻塞 ,直接对话框窗口被关闭)
		this.setVisible(true);
	}
}

zip查看目录

在这里插入图片描述

package my;

import java.io.File;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class TestUnzip
{

	public static void main(String[] args) throws Exception
	{
		// 准备一个ZIP文件 
		// 注意:文件的位置,直接放在项目根目录下
		File scrFile = new File("1.zip");
		
		// 在Windows指定GBK,在Linux一般为UTF-8
		// 若字符集不匹配,则文件名和路径里的中文将是乱码
		ZipFile zipFile = new ZipFile(scrFile, Charset.forName("GBK"));
		
		int fileCount = 0;
		long totalSize = 0;
		Enumeration<?> entries = zipFile.entries();
        while(entries.hasMoreElements())
        {
        	ZipEntry entry = (ZipEntry) entries.nextElement();
        	
        	if(entry.isDirectory())
        	{
        		// 该项是目录
        		System.out.println("** " + entry.getName());
        	}
        	else
        	{
        		// 该项是文件
        		System.out.println("   " + entry.getName());
        		fileCount += 1; // 文件个数
        		totalSize += entry.getSize();
        		
        	}
        }
        
        System.out.println("-----------------------");
        System.out.println("文件总数: " + fileCount);
        System.out.println("文件总数: " + totalSize);
        
        zipFile.close();
	}

}

zip解压缩

在这里插入图片描述

package my;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class TestUnzip
{
	public static void main(String[] args) throws Exception
	{
		// 准备一个ZIP文件
		// 注意:文件的位置,直接放在项目根目录下
		File scrFile = new File("1.zip");
		
		// 指定解压缩的目标位置
		File dstDir = new File("C:/Users/Administrator/Desktop/");
		dstDir.mkdirs();
		
		// 在Windows指定GBK,在Linux一般为UTF-8
		// 若字符集不匹配,则文件名和路径里的中文将是乱码
		ZipFile zipFile = new ZipFile(scrFile, Charset.forName("GBK"));

		// 遍历每一条
		Enumeration<?> entries = zipFile.entries();
		while (entries.hasMoreElements())
		{
			ZipEntry entry = (ZipEntry) entries.nextElement();
			if (entry.isDirectory()) continue;
			
			System.out.println("处理文件:" + entry.getName());
			
			// entry.getName() 获取条目的路径
			File dstFile = new File(dstDir, entry.getName());
			dstFile.getParentFile().mkdirs(); // 创建所在的子目录

			// 从zip文件中解出数据
			InputStream inputStream = zipFile.getInputStream(entry);
			OutputStream outputStream = new FileOutputStream(dstFile);
			try
			{
				byte[] buf = new byte[4096];
				while(true)
				{
					int n = inputStream.read(buf);
					if(n <= 0)break;			
					outputStream.write(buf, 0, n);
				}
			} 
			finally
			{
				// 确保文件被关闭
				try{ inputStream.close(); } catch (Exception e){}
				try{ outputStream.close(); } catch (Exception e){}
			}
		}

		// 最后要记得关闭文件
		zipFile.close();
	}

}

显示zip目录,解压缩操作(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值