在編寫完進度條後,我們有時候會遇到它完全不動的情況,小夥伴們知道是什麼原因嗎?下面聽小編為你們講解講解。
進度條不動可能是因為這個原因,“當應用程式在事件線程中執行長時間的操作時,會阻塞正常的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常見問題及解決方法還有不懂的話就來我們網站看看吧。
推薦閱讀: