更新時間:2022-10-31 10:09:17 來源:動力節(jié)點 瀏覽3045次
有時,在程序中運行的任務(wù)可能需要一段時間才能完成。用戶友好的程序向用戶提供一些指示,表明任務(wù)正在發(fā)生、任務(wù)可能需要多長時間以及已經(jīng)完成了多少工作。一種表示工作的方式,也許是進度量,是使用動畫圖像。
另一種指示工作的方法是使用 Cursor類和Component-defined setCursor方法設(shè)置等待光標。例如,以下代碼使等待光標在光標結(jié)束時顯示container(包括它包含的任何未指定光標的組件):
container.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
要傳達任務(wù)的完成程度,您可以使用如下進度條:

有時您無法立即確定長時間運行的任務(wù)的長度,或者該任務(wù)可能會長時間停留在相同的完成狀態(tài)。您可以通過將進度條置于不確定模式來顯示沒有可測量進度的工作。不確定模式下的進度條會顯示動畫以指示工作正在進行。一旦進度條可以顯示更有意義的信息,您應(yīng)該將其切換回其默認的確定模式。在 Java 外觀中,不確定的進度條如下所示:

Swing 提供了三個類來幫助您使用進度條:
JProgressBar
一個可視組件,以圖形方式顯示總?cè)蝿?wù)已完成多少。使用不確定模式部分告訴您如何在任務(wù)范圍已知之前為進度條設(shè)置動畫以顯示活動。
ProgressMonitor
不是可見組件。相反,此類的一個實例監(jiān)視任務(wù)的進度并在必要時彈出一個對話框。
ProgressMonitorInputStream
帶有附加進度監(jiān)視器的輸入流,它監(jiān)視從流中讀取的內(nèi)容。您可以像使用Basic I/O中描述的任何其他輸入流一樣使用此流的實例 。您可以通過調(diào)用來獲取流的進度監(jiān)視器,getProgressMonitor并按照如何使用進度監(jiān)視器中的說明對其進行配置。
在您看到正在運行的進度條和進度監(jiān)視器后,決定是使用進度條還是進度監(jiān)視器可以幫助您確定哪個適合您的應(yīng)用程序。
這是一個小型演示應(yīng)用程序的圖片,它使用進度條來測量在自己的線程中運行的任務(wù)的進度:

//聲明成員變量的地方:
JProgressBar 進度條;
...
//GUI的構(gòu)建位置:
progressBar = new JProgressBar(0, task.getLengthOfTask());
進度條.setValue(0);
progressBar.setStringPainted(true);
創(chuàng)建進度條的構(gòu)造函數(shù)設(shè)置進度條的最小值和最大值。您還可以使用setMinimum和設(shè)置這些值setMaximum。這個程序中使用的最小值和最大值是 0 和任務(wù)的長度,這是許多程序和任務(wù)的典型特征。但是,進度條的最小值和最大值可以是任何值,甚至是負值。該代碼段還將進度條的當(dāng)前值設(shè)置為 0。
調(diào)用setStringPainted使進度條在其范圍內(nèi)顯示已完成任務(wù)百分比的文本指示。默認情況下,進度條顯示其getPercentComplete方法返回的值,格式為百分比,例如33%?;蛘?,您可以通過調(diào)用將默認值替換為不同的字符串setString。例如,
if ( /*...完成一半...*/ )
progressBar.setString("到了一半!");
當(dāng)用戶單擊StartTask時,會創(chuàng)建并執(zhí)行內(nèi)部類的一個實例。
公共無效actionPerformed(ActionEvent evt){
startButton.setEnabled(false);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
完成=假;
任務(wù)=新任務(wù)();
task.addPropertyChangeListener(this);
任務(wù).執(zhí)行();
}
Task的子類是 javax.swing.SwingWorker。該Task實例為 做三件重要的事情ProgressBarDemo:
該實例doInBackground在單獨的線程中調(diào)用 。這是實際執(zhí)行長時間運行的任務(wù)的地方。使用后臺線程而不是事件調(diào)度線程可以防止用戶界面在任務(wù)運行時凍結(jié)。
當(dāng)后臺任務(wù)完成時,實例調(diào)用done事件調(diào)度線程中的方法。
該實例維護一個綁定屬性 ,progress該屬性已更新以指示任務(wù)的進度。propertyChange每次progress更改時都會調(diào)用該方法。
有關(guān) . _ _ _ SwingWorker_
后臺任務(wù)ProgressBarDemo通過以隨機間隔報告隨機進度量來模擬真實任務(wù)。該方法通過更新進度條propertyChange來響應(yīng)任務(wù)屬性的變化:progress
公共無效propertyChange(PropertyChangeEvent evt){
如果(!完成){
int 進度 = task.getProgress();
進度條.setValue(進度);
taskOutput.append(String.format(
"已完成 %d%% 的任務(wù)。\n", 進度));
}
后臺任務(wù)完成后,任務(wù)的done方法重置進度條:
公共無效完成(){
//告訴進度監(jiān)聽器停止更新進度條。
完成=真;
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(true);
設(shè)置游標(空);//關(guān)閉等待光標
progressBar.setValue(progressBar.getMinimum());
taskOutput.append("完成!\n");
}
請注意,該done方法將done字段設(shè)置為true,以防止propertyChange對進度條進行進一步更新。這是必要的,因為progress屬性的最終更新可能發(fā)生在done調(diào)用之后。
設(shè)置為ProgressBarDemo2不確定模式,直到實際進度開始:
公共無效propertyChange(PropertyChangeEvent evt){
如果(!完成){
int 進度 = task.getProgress();
如果(進度== 0){
progressBar.setIndeterminate(true);
taskOutput.append("還沒有進展\n");
} 別的 {
progressBar.setIndeterminate(false);
進度條.setString(null);
進度條.setValue(進度);
taskOutput.append(String.format(
"已完成 %d%% 的任務(wù)。\n", 進度));
}
}
}
代碼中的其他更改與字符串顯示有關(guān)。顯示字符串的進度條可能比不顯示字符串的進度條要高,并且,作為演示設(shè)計者,我們已經(jīng)武斷地決定該進度條應(yīng)該僅在默認的確定模式下顯示字符串。但是,我們希望避免在更改模式時進度條更改高度可能導(dǎo)致的布局丑陋。因此,代碼保留在調(diào)用中,setStringPainted(true)但添加了調(diào)用,setString("")因此不會顯示任何文本。稍后,當(dāng)進度條從不確定模式切換到確定模式時,調(diào)用setString(null)會使進度條顯示其默認字符串。
我們沒有做的一項更改是progressBar.setValue從progress事件處理程序中刪除調(diào)用。該調(diào)用不會造成任何傷害,因為不確定的進度條不使用其 value 屬性,除非可能將其顯示在狀態(tài)字符串中。事實上,讓進度條的數(shù)據(jù)盡可能保持最新是一種很好的做法,因為某些外觀可能不支持不確定模式。
相關(guān)閱讀