来自 Oracle 的 JProgressBar [英] JProgressBar from Oracle

查看:40
本文介绍了来自 Oracle 的 JProgressBar的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 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 SwingWorkers 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 Strings with == is bad idea (and freaks me out :P)

这篇关于来自 Oracle 的 JProgressBar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆