java中的進度條的顯示
最近需要用到進度條,於是就查看了一下oracle的文件,看了一下java中進度條的顯示方法,現在就總結一下。
java提供了三種關於進度條的顯示類。
那麼這三種之間有什麼區別呢?下面我進行一下簡單的介紹,並提供例子方便大家理解。
JprogressBar
作為一個元件,顯示 當前完成了多少工作。
ProgressMonitor
這個不能作為一個元件顯示,他會彈出一個框,在框裡面來顯示進度。
ProgressMonitorInputStream
這個從名字就看出來了這個類的作用了,就是將這個輸入流通過progressMonitorInputStream包裝,然後通過呼叫getProgressMonitor
可以檢視進度。
咱們主要用的就是前兩個,所有我再次介紹一下前兩種方法。其實JprogressBar和ProgressMonitor的原理都是一樣的。首先建立一個類繼承SwingWorker,這個類的功能主要有三個:
1:他會在doInBackground這個方法裡面,執行你所需要乾的事情。這個方法會開啟一個執行緒,這樣的使用者就不會在此阻塞而幹不了其他的事情了。
2:當這個任務結束的時候,會呼叫done方法,你可以在這裡面寫入自己的實現。例如,彈出一個框顯示任務結束。
3:有一個int型別的變數progress,這個變數就是顯示任務的執行進度,每次progress改變的時候,propertyChange
這樣思路就更加清晰了,首先建立的類A繼承SwingWorker,在doInBackground這個方法裡面寫上你需要顯示進度的任務,並在適當的時候通過呼叫setProgress(value)方法改變progress這個值,value代表任務進行到多少了,最少是0,最大是100(代表任務結束了),當然使用者也可以自己進行設定最小最大值。如果有需要的話,也可以在done方法裡面寫上自己的實現。
建立另外一個類B,這個類的作用就是通過進度條來顯示你的任務進行到哪個地步了。在類A當中提過了,在doInBackground中,使用者通過改變progress來表示任務執行的情況,所以只要當類A中的progress一改變我就把值得到,這個值就是當前任務的完成率,然後在類B中顯示到進度條上就可以了。所以我們要給類A中的progress新增一個監聽器,這個監聽器其實就是類B。因此B需要實現PropertyChangeListener這個介面,實現PropertyChange()這個方法.
接下來要做的就是例項化類A,並新增監聽器,然後執行類A的任務就可以了。如下例:
import
java.awt.*;
import
java.awt.event.*;
import
javax.swing.*;
import
java.beans.*;
import
java.util.Random;
public
class
ProgressBarDemo
extends
JPanel
implements
ActionListener,
PropertyChangeListener {
private
JProgressBar progressBar;
private
JButton startButton;
private
JTextArea taskOutput;
private
Task task;
class
Task
extends
SwingWorker<Void, Void> {
/*
* Main task. Executed in background thread.
*/
@Override
public
Void doInBackground() {
Random random =
new
Random();
int
progress =
0
;
//Initialize progress property.
setProgress(
0
);
while
(progress <
100
) {
//Sleep for up to one second.
try
{
Thread.sleep(random.nextInt(
1000
));
}
catch
(InterruptedException ignore) {}
//Make random progress.
progress += random.nextInt(
10
);
setProgress(Math.min(progress,
100
));
}
return
null
;
}
/*
* Executed in event dispatching thread
*/
@Override
public
void
done() {
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(
true
);
setCursor(
null
);
//turn off the wait cursor
taskOutput.append(
"Done!\n"
);
}
}
public
ProgressBarDemo() {
super
(
new
BorderLayout());
//Create the demo's UI.
startButton =
new
JButton(
"Start"
);
startButton.setActionCommand(
"start"
);
startButton.addActionListener(
this
);
progressBar =
new
JProgressBar(
0
,
100
);
progressBar.setValue(
0
);
progressBar.setStringPainted(
true
);
taskOutput =
new
JTextArea(
5
,
20
);
taskOutput.setMargin(
new
Insets(
5
,
5
,
5
,
5
));
taskOutput.setEditable(
false
);
JPanel panel =
new
JPanel();
panel.add(startButton);
panel.add(progressBar);
add(panel, BorderLayout.PAGE_START);
add(
new
JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(
20
,
20
,
20
,
20
));
}
/**
* Invoked when the user presses the start button.
*/
public
void
actionPerformed(ActionEvent evt) {
startButton.setEnabled(
false
);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
//Instances of javax.swing.SwingWorker are not reusuable, so
//we create new instances as needed.
task =
new
Task();
task.addPropertyChangeListener(
this
);
task.execute();
}
/**
* Invoked when task's progress property changes.
*/
public
void
propertyChange(PropertyChangeEvent evt) {
if
(
"progress"
== evt.getPropertyName()) {
int
progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
taskOutput.append(String.format(
"Completed %d%% of task.\n"
, task.getProgress()));
}
}
/**
* Create the GUI and show it. As with all GUI code, this must run
* on the event-dispatching thread.
*/
private
static
void
createAndShowGUI() {
//Create and set up the window.
JFrame frame =
new
JFrame(
"ProgressBarDemo"
);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane =
new
ProgressBarDemo();
newContentPane.setOpaque(
true
);
//content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(
true
);
}
public
static
void
main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(
new
Runnable() {
public
void
run() {
createAndShowGUI();
}
});
}
}
這個是一個JProgressBar的例子,下面是一個ProgressMonitor的例子,讀者可以比較一下。
import
java.awt.*;
import
java.awt.event.*;
import
javax.swing.*;
import
java.beans.*;
import
java.util.Random;
public
class
ProgressMonitorDemo
extends
JPanel
implements
ActionListener,
PropertyChangeListener {
private
ProgressMonitor progressMonitor;
private
JButton startButton;
private
JTextArea taskOutput;
private
Task task;
class
Task
extends
SwingWorker<Void, Void> {
@Override
public
Void doInBackground() {
Random random =
new
Random();
int
progress =
0
;
setProgress(
0
);
try
{
Thread.sleep(
1000
);
while
(progress <
100
&& !isCancelled()) {
//Sleep for up to one second.
Thread.sleep(random.nextInt(
1000
));
//Make random progress.
progress += random.nextInt(
10
);
setProgress(Math.min(progress,
100
));
}
}
catch
(InterruptedException ignore) {}
return
null
;
}
@Override
public
void
done() {
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(
true
);
progressMonitor.setProgress(
0
);
}
}
public
ProgressMonitorDemo() {
super
(
new
BorderLayout());
//Create the demo's UI.
startButton =
new
JButton(
"Start"
);
startButton.setActionCommand(
"start"
);
startButton.addActionListener(
this
);
taskOutput =
new
JTextArea(
5
,
20
);
taskOutput.setMargin(
new
Insets(
5
,
5
,
5
,
5
));
taskOutput.setEditable(
false
);
add(startButton, BorderLayout.PAGE_START);
add(
new
JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(
20
,
20
,
20
,
20
));
}
/**
* Invoked when the user presses the start button.
*/
public
void
actionPerformed(ActionEvent evt) {
progressMonitor =
new
ProgressMonitor(ProgressMonitorDemo.
this
,
"Running a Long Task"
,
""
,
0
,
100
);
progressMonitor.setProgress(
0
);
task =
new
Task();
task.addPropertyChangeListener(
this
);
task.execute();
startButton.setEnabled(
false
);
}
/**
* Invoked when task's progress property changes.
*/
public
void
propertyChange(PropertyChangeEvent evt) {
if
(
"progress"
== evt.getPropertyName() ) {
int
progress = (Integer) evt.getNewValue();
progressMonitor.setProgress(progress);
String message =
String.format(
"Completed %d%%.\n"
, progress);
progressMonitor.setNote(message);
taskOutput.append(message);
if
(progressMonitor.isCanceled() || task.isDone()) {
Toolkit.getDefaultToolkit().beep();
if
(progressMonitor.isCanceled()) {
task.cancel(
true
);
taskOutput.append(
"Task canceled.\n"
);
}
else
{
taskOutput.append(
"Task completed.\n"
);
}
startButton.setEnabled(
true
);
}
}
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private
static
void
createAndShowGUI() {
//Create and set up the window.
JFrame frame =
new
JFrame(
"ProgressMonitorDemo"
);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane =
new
ProgressMonitorDemo();
newContentPane.setOpaque(
true
);
//content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(
true
);
}
public
static
void
main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(
new
Runnable() {
public
void
run() {
createAndShowGUI();
}
});
}
}
下面講一講我們什麼時候用JProgressBar,什麼時候用ProgressMonitor呢?
用到JProgressBar的時候
1:當你需要對進度條進行更加細緻的控制的時候,比如給進度條新增事件等等。
2:你需要顯示跟進度條有一定關聯關係的元件的時候。
3:你需要同時顯示多個進度條。
4:這個進度條可以重複使用的時候。
用ProgressMonitor的時候
1:只是想在一個彈出框裡面簡單的顯示進度而已。
2:這個任務不是很重要,使用者對此也不是很感興趣。基於此,ProgressMonitor還提供給了使用者cancel的按鈕。
3:需要不定時得向用戶傳遞資訊(關於任務的資訊,例如下一步需要幹嘛)。