在编写完进度条后,我们有时候会遇到它完全不动的情况,小伙伴们知道是什么原因吗?下面听小编为你们讲解讲解。
进度条不动可能是因为这个原因,“当应用程序在事件线程中执行长时间的操作时,会阻塞正常的AWT事件处理,因此阻止了重绘操作的发生”,即API本身就是线程不安全的。造成这个错误的原因,就是在run方法内直接写:
progressBar.setValue(jd);
最终修改示例:
import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JTextField; public class Exp10_3 extends JFrame implements Runnable { boolean b = false; // 线程执行的标志 int jd = 0; // 当前进度 long sum = 0; // 当前共复制的长度 JButton button1 = new JButton("被复制"); JTextField beCyFile = new JTextField(30); JButton button2 = new JButton("复制到"); JTextField CyToDir = new JTextField(30); JButton Start = new JButton("开始复制"); JLabel label = new JLabel("进度"); JProgressBar progressBar = new JProgressBar(); void initUI() { JPanel top1 = new JPanel(); JPanel top2 = new JPanel(); JPanel end = new JPanel(); top1.add(button1); top1.add(beCyFile); top2.add(button2); top2.add(CyToDir); setLayout(new GridLayout(4, 1)); add(top1); add(top2); add(Start); progressBar.setStringPainted(true); // 设置进度条上字符串可显示 progressBar.setBackground(Color.GREEN); // 设置进度条颜色 end.add(label); end.add(progressBar); add(end); button1.addActionListener(new ActionListener() { // 将选择文件的绝对路径显示到被复制后的文本框内 @Override public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); fc.setFileHidingEnabled(false); // 显示隐藏文件 fc.setMultiSelectionEnabled(false); // 允许多选 fc.setDialogTitle("请选择要复制的文件"); if (fc.showOpenDialog(Exp10_3.this) == JFileChooser.APPROVE_OPTION) { beCyFile.setText(fc.getSelectedFile() .getAbsolutePath()); CyToDir.setText(fc.getSelectedFile() .getParent()); // 获取file文件的父目录(强大的API) 自我设定:默认复制到同一目录 } } }); button2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); // 仅仅能选择目录 fc.setDialogTitle("请选择要复制到的路径"); if (fc.showOpenDialog(Exp10_3.this) == JFileChooser.APPROVE_OPTION) { CyToDir.setText(fc.getSelectedFile() .getAbsolutePath()); } } }); Start.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jd = 0; b = true; try { String file1Path = beCyFile.getText(); File file1 = new File(beCyFile.getText()); // 被复制的文件 String file2Path = CyToDir.getText() + "\\copy" + file1.getName(); // 复制完后新文件路径名 File file2 = new File(file2Path); // 新建复制文件 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file1Path)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2Path)); byte[] be = new byte[1024 * 1024]; // 之前定义为b和boolean重复了 屏蔽了全局标志b int len = bis.read(be); long sum = 0; long file1len = file1.length(); while (-1 != len) { bos.write(be, 0, len); // 一次读一个字节数组 换行也会读 不用自动换行了 bos.flush(); sum += len; jd = (int)(sum * 1.0 / file1len * 100); // 之前没有乘1.0 且多写了一个(int) 导致jd一直是0 最后一次突变100 len = bis.read(be); } 最后再绘一次 Dimension d = progressBar.getSize(); Rectangle rect = new Rectangle(0, 0, d.width, d.height); progressBar.setValue(jd); progressBar.paintImmediately(rect); b = false; System.out.println("b=" + b); } catch (IOException e1) { e1.printStackTrace(); } } }); Thread t = new Thread(this); t.start(); pack(); setLocationRelativeTo(null); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { Exp10_3 t = new Exp10_3(); t.initUI(); } @Override public void run() { while (true) { if (b) { //progressBar.setValue(jd);//之前run内就这一行,进度条一直不刷新 Dimension d = progressBar.getSize(); Rectangle rect = new Rectangle(0, 0, d.width, d.height); progressBar.setValue(jd); progressBar.paintImmediately(rect); if (jd == 100) { b = false; //System.out.println("run内b=" + b);// 不能写return 此进程不能结束 一直开着 } } //System.out.println("我没有结束");//删了此行进度条就又不刷新了 //第一次改进 上面一行换成下面5行 即输出操作改成停顿1ms try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }
以上就是本篇文章的所有内容,对于一些java常见问题及解决方法还有不懂的话就来我们网站看看吧。
推荐阅读: