来自 Oracle 的 JProgressBar [英] JProgressBar from Oracle
问题描述
我从 oracle 网站下载了一个小型 Java 项目来创建进度条.
我理解它,但我需要以不同的方式应用它,应用程序正在后台创建一个线程,以便可以相应地更新进度条(doInBackground()
).>
我的问题是,如何用我的应用程序中的方法(方法只是对数据库进行一种批处理)替换此应用程序后台中的此类进程,有人可以帮忙吗?
这是 Oracle 的代码:
import java.awt.*;导入 java.awt.event.*;导入 javax.swing.*;导入 java.beans.*;导入 java.util.Random;公共类 ProgressBarDemo2 扩展了 JPanel实现 ActionListener、PropertyChangeListener {私人 JProgressBar 进度条;私人 JButton 开始按钮;私有 JTextArea 任务输出;私人任务;class Task 扩展了 SwingWorker{/** 主要任务.在后台线程中执行.*/@覆盖公共无效 doInBackground() {随机随机=新随机();int 进度 = 0;//初始化进度属性.设置进度(0);//休眠至少一秒模拟启动".尝试 {Thread.sleep(1000 + random.nextInt(2000));} catch (InterruptedException 忽略) {}而(进度<100){//最多休眠一秒.尝试 {Thread.sleep(random.nextInt(1000));} catch (InterruptedException 忽略) {}//随机进行.进度 += random.nextInt(10);setProgress(Math.min(progress, 100));}返回空;}/** 在事件调度线程中执行*/公共无效完成(){Toolkit.getDefaultToolkit().beep();startButton.setEnabled(true);taskOutput.append("完成!\n");}}公共 ProgressBarDemo2() {超级(新的边框布局());//创建演示的用户界面.startButton = new JButton("开始");startButton.setActionCommand("开始");startButton.addActionListener(this);progressBar = new JProgressBar(0, 100);progressBar.setValue(0);//现在调用 setStringPainted 使进度条高度//无论字符串是否显示都保持不变.progressBar.setStringPainted(true);taskOutput = new JTextArea(5, 20);taskOutput.setMargin(new Insets(5,5,5,5));taskOutput.setEditable(false);JPanel 面板 = new JPanel();panel.add(startButton);面板添加(进度条);添加(面板,BorderLayout.PAGE_START);添加(新 JScrollPane(任务输出),BorderLayout.CENTER);setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));}/*** 当用户按下开始按钮时调用.*/公共无效动作执行(ActionEvent evt){progressBar.setIndeterminate(true);startButton.setEnabled(false);//javax.swing.SwingWorker 的实例不可重用,所以//我们根据需要创建新实例.任务=新任务();task.addPropertyChangeListener(this);任务.执行();}/*** 当任务的进度属性改变时调用.*/公共无效propertyChange(PropertyChangeEvent evt){if ("progress" == evt.getPropertyName()) {int progress = (Integer) evt.getNewValue();progressBar.setIndeterminate(false);progressBar.setValue(progress);taskOutput.append(String.format("已完成 %d%% 的任务.\n", 进度));}}/*** 创建 GUI 并显示它.与所有 GUI 代码一样,这必须运行* 在事件调度线程上.*/私有静态无效 createAndShowGUI() {//创建并设置窗口.JFrame frame = new JFrame("ProgressBarDemo2");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//创建并设置内容窗格.JComponent newContentPane = new ProgressBarDemo2();newContentPane.setOpaque(true);//内容窗格必须是不透明的frame.setContentPane(newContentPane);//显示窗口.框架.pack();frame.setVisible(true);}公共静态无效主(字符串 [] args){//为事件调度线程安排一个作业://创建并显示此应用程序的 GUI.javax.swing.SwingUtilities.invokeLater(new Runnable() {公共无效运行(){createAndShowGUI();}});}}
首先,我建议定义一个可进行"状态的概念
public interface Progressable {public void setProgress(int progress);//我更喜欢 double,但我们会将它与 API 的其余部分保持一致}
然后,您的任务的入口点将引用Progressable
公共类 MySuperAwesomeLongRunningTask ... {//...私人 Progressable 可进展的;public void performTask(Progressable progressable) {this.prgressable = 可进步}protected void methodThatDoesSomeWork() {//做一些超级骗子的工作...//以某种方式计算该工作的进度,//基于你的实现...int 进度 = ...;progressable.setProgress(progress);}}
然后,创建一个 SwingWorker
实现 Progressable
并调用你的工作...
class Task extends SwingWorker实现 Progressable {私人 MySuperAwesomeLongRunningTask taskToBeDone;公共任务(MySuperAwesomeLongRunningTask taskToBeDone){self.taskToBeDone = taskToBeDone;}/** 主要任务.在后台线程中执行.*/@覆盖公共无效 doInBackground() {taskToBeDone.performTask(this);返回空;}/** 在事件调度线程中执行*/公共无效完成(){//你需要做什么...}}
现在,因为 SwingWorker
已经有一个名为 setProgress(int)
的方法,它自动符合 Progressable
(只要你实现它),所以当 MySuperAwesomeLongRunningTask
调用 setProgress
时,它实际上会调用 SwingWorker
的实现.
这意味着,其余的代码基本上保持不变,期待,我会改变
if ("progress" == evt.getPropertyName()) {
到
if ("progress".equals(evt.getPropertyName())) {
因为将 String
与 ==
进行比较是个坏主意(这让我很害怕:P)
I've downloaded a small Java project from oracle website to create a progress bar.
I understand it, but I need to apply it in a different way, the application is creating a thread in the background so the progress bar can be updated accordingly (doInBackground()
).
My question is, how can I replace this kind of process in the background in this application by a method from my application (method is just doing a kind of batch processing on a database), can someone help please?
Here is code by Oracle:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.util.Random;
public class ProgressBarDemo2 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);
//Sleep for at least one second to simulate "startup".
try {
Thread.sleep(1000 + random.nextInt(2000));
} catch (InterruptedException ignore) {}
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 dispatch thread
*/
public void done() {
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(true);
taskOutput.append("Done!\n");
}
}
public ProgressBarDemo2() {
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);
//Call setStringPainted now so that the progress bar height
//stays the same whether or not the string is shown.
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) {
progressBar.setIndeterminate(true);
startButton.setEnabled(false);
//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.setIndeterminate(false);
progressBar.setValue(progress);
taskOutput.append(String.format(
"Completed %d%% of task.\n", progress));
}
}
/**
* 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("ProgressBarDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new ProgressBarDemo2();
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();
}
});
}
}
First, I'd recommend by defining a concept of a "progressable" state
public interface Progressable {
public void setProgress(int progress); // I prefer double, but we'll keep it inline with the rest of the API
}
Then, the entry point for your tasks would take a reference to Progressable
public class MySuperAwesomeLongRunningTask ... {
//...
private Progressable progressable;
public void performTask(Progressable progressable) {
this.prgressable = progressable
}
protected void methodThatDoesSomeWork() {
// Do some super duper work...
// calculate the progress of that work some how,
// based on your implementation...
int progress = ...;
progressable.setProgress(progress);
}
}
Then, create a SwingWorker
which implements Progressable
and calls your work...
class Task extends SwingWorker<Void, Void> implements Progressable {
private MySuperAwesomeLongRunningTask taskToBeDone;
public Task(MySuperAwesomeLongRunningTask taskToBeDone) {
self.taskToBeDone = taskToBeDone;
}
/*
* Main task. Executed in background thread.
*/
@Override
public Void doInBackground() {
taskToBeDone.performTask(this);
return null;
}
/*
* Executed in event dispatch thread
*/
public void done() {
// What ever you need to do...
}
}
Now, because SwingWorker
already has a method called setProgress(int)
it automatically conforms to Progressable
(so long as you implement it), so when MySuperAwesomeLongRunningTask
calls setProgress
, it will actually be calling the SwingWorker
s implementation.
This means, that the rest of the code basically remains the same, expect, I'd change
if ("progress" == evt.getPropertyName()) {
to
if ("progress".equals(evt.getPropertyName())) {
because comparing String
s with ==
is bad idea (and freaks me out :P)
这篇关于来自 Oracle 的 JProgressBar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!