預設之進度條或圈可能無法滿足各種版型,因此本次採用輪播圖片的方式,再加上實作Runnable介面以實現多線程(/執行緒)來不斷地執行該動畫,以達到進度圈之樣貌,並在此給予範例以供各位參考與學習。
1. Runnable和Thread的區別
2. Java中有二種方式可實現多線程,一為繼承Thread類別,另一則為實作Runnable介面。
a. 繼承Thread類別
Class只要extendsThread,並覆寫run()方法,即可實現多線程之操作,但因一個Class只能繼承一個父類別,因此大多是透過實作Runnable介面來完成的。
b. 實作Runnable介面
(1) 一個Class只要implementsRunnable,且覆寫run()方法,即可實現多線程之操作,但因Runnable定義的子類別中没有start()方法,因此利用public Thread(Runnable target)建構子,來接受Runnable的子類實例,並再透過Thread來啟動之。
(2) Ex:
CustomThreadct = new CustomThread(“自製線程內容”);
Thread thread = new Thread(ct);
thread.start();
c. 差異之間的小結
多線程大多皆以「實作Runnable介面」為主,因為其好處在於:避免侷限於只能繼承一個父類別之問題,其能一個類別實作好幾個介面。
- 範例:在此展示一個共有8張相似之圖示,並於每180毫秒就會重新變更該圖片之範例,其主要為達到下載中的進度圈之效果。
/**
*
* @author Elsa
*/
public class ProgressBarAnimation extends JFrame {
Thread thread = new Thread(new ActionThread()); // 創建線程(thread)
boolean flag = true; // 用於標示動畫是否為開始播放(/暫停/繼續)之狀態
boolean stop = false; // 用於標示動畫是否為停止之狀態
final JLabel labImge, labStatus; // 用於顯示圖片之label、和顯示[下載中]之狀態文字
JPanel panelLoadingContent; // 用於顯示裝載提示下載中之狀態文字與圖片
JButton btnStart, btnStop; // 用於啟動或停止動畫執行之按鈕
String picturePath; // 用於儲存圖片路徑之變數
/*
* 初始化各元件與設定
*/
public ProgressBarAnimation() {
// 1.初始化Frame之相關設定
setSize(350, 350);
setTitle("動畫進度圈之範例");
getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
// 2.生成各元件
panelLoadingContent = new javax.swing.JPanel();
labImge = new JLabel();
labStatus = new javax.swing.JLabel();
btnStart = new javax.swing.JButton();
btnStop = new javax.swing.JButton();
// 3.初始化panelLoadingContent、labImge、labStatus之設定,並先隱藏該panel
panelLoadingContent.setOpaque(false);
panelLoadingContent.setBackground(new java.awt.Color(255, 255, 255));
panelLoadingContent.setMaximumSize(new java.awt.Dimension(100, 100));
panelLoadingContent.setMinimumSize(new java.awt.Dimension(100, 100));
panelLoadingContent.setLayout(new java.awt.BorderLayout());
labImge.setIcon(new javax.swing.ImageIcon(getClass().getResource("/test2/Res/progress_bar_circles_01.png")));
panelLoadingContent.add(labImge, java.awt.BorderLayout.CENTER);
labStatus.setText("下載中");
labStatus.setForeground(new java.awt.Color(0, 102, 255));
labStatus.setFont(new java.awt.Font("微軟正黑體", 1, 16));
labStatus.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
panelLoadingContent.add(labStatus, java.awt.BorderLayout.SOUTH);
getContentPane().add(panelLoadingContent, new org.netbeans.lib.awtextra.AbsoluteConstraints(120, 100, -1, -1));
panelLoadingContent.setVisible(false);
// 4.設定[開始]和[停止]按鈕之ActionListener
btnStart.setText("開 始");
getContentPane().add(btnStart, new org.netbeans.lib.awtextra.AbsoluteConstraints(100, 220, -1, -1));
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent arg0) {
// 若線程為空(即null),則重新創建線程物件
if (thread == null)
thread = new Thread(new ActionThread());
// 判斷該活動線程是否正在執行,若false,則執行下述之代碼,以啟動線程的執行
if (!thread.isAlive()) {
panelLoadingContent.setVisible(true);
stop = false;
flag = true;
thread.start();
}
}
});
btnStop.setText("停 止");
getContentPane().add(btnStop, new org.netbeans.lib.awtextra.AbsoluteConstraints(152, 220, -1, -1));
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent arg0) {
panelLoadingContent.setVisible(false);
stop = true; // 設置為true,以停止播放動畫
}
});
}
▲初始化各元件與設定之程式
/*
* 用於實現動畫的線程 (其用於每180毫秒重新設定圖片,以達到動畫之效果)
*/
private class ActionThread implements Runnable {
private int index = 0; // 用於控制圖片的編號
public void run() {
while (true) {
// 如stop為true,則停止動畫之播放
if (stop) {
thread = null; // 銷毀線程
break; // 跳出循環,結束線程的執行
}
// 如為播放狀態者(即flag=true),則開始設定圖片
if (flag) {
String picture = "/test2/Res/progress_bar_circles_0"; // 設置圖片存放的位置路徑
index++;
if (index <= 8) { // 動畫圖示共為8張,以讓其一直循環這8張圖
picturePath = picture + index + ".png";
if(index % 2 == 0) // 取餘數,讓奇偶數之圖示時的狀態文字有不一樣的色調,以顯示微跳動之感
labStatus.setForeground(new java.awt.Color(0,153,255));
else
labStatus.setForeground(new java.awt.Color(0, 102, 255));
} else {
index = 1;
picturePath = picture + index + ".png";
labStatus.setForeground(new java.awt.Color(0, 102, 255));
}
// 設置顯示之圖片
labImge.setIcon(new javax.swing.ImageIcon(getClass().getResource(picturePath)));
try {
Thread.sleep(180); // 讓線程休眠180毫秒,再設置下一張圖片
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
}
▲用於實現動畫線程之程式
/*
* 視窗關閉事件
*/
public void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING)
System.exit(0);
}
▲視窗關閉事件與主程式等程式
3. 執行結果
▲尚未啟動之樣貌
▲執行中之樣貌
參考網址:
http://blog.csdn.net/wwww1988600/article/details/7309070