最近需要用到进度条,于是就查看了一下oracle的文档,看了一下java中进度条的显示方法,现在就总结一下。
java提供了三种关于进度条的显示类。
3:ProgressMonitorInputStream
(进程监视流)
那么这三种之间有什么区别呢?下面我进行一下简单的介绍,并提供例子方便大家理解。
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();
}
});
}
}
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:需要不定时得向用户传递信息(关于任务的信息,例如下一步需要干嘛)。