【问题标题】:Progress Bar for a GUI application using Java使用 Java 的 GUI 应用程序的进度条
【发布时间】:2018-08-06 04:02:01
【问题描述】:

我正在尝试为在 GUI 运行之前下载信息的应用程序编写进度条。因为这是一个下载和整理信息的漫长过程,所以我想通知用户进度。我决定在游戏后期使用进度条,因此,大部分代码都是编写的,我试图将进度条合并到代码中,而不需要对代码进行大刀阔斧的改造。以下是进度条的代码。目前,进度条会在所有内容运行并弹出 GUI 后出现。

static class PopulatingCardsWorker extends SwingWorker<Void, Integer> {

    JProgressBar jpb;
    int max;
    JLabel label;

    public PopulatingCardsWorker(JProgressBar jpb, int maximum, JLabel label) {
        this.jpb = jpb;
        this.max = maximum;
        this.label = label;
    }

    @Override
    protected void process(List<Integer> chunks) {
        int i = chunks.get(chunks.size()-1);
        jpb.setValue(i); // The last value in this array is all we care about.
        System.out.println(i);
        label.setText("Loading " + i + " of " + max);
    }

    @Override
    protected Void doInBackground() throws Exception {
        for(int i = 0; i < max; i++) {
            Thread.sleep(10); // Illustrating long-running code.
            publish(i);
        }
        return null;
    }

    @Override
    protected void done() {
        try {
            get();
            JOptionPane.showMessageDialog(jpb.getParent(), "Success", "Success", JOptionPane.INFORMATION_MESSAGE);
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private static void go(int max) {
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JLabel label = new JLabel("Loading...");
    JProgressBar jpb = new JProgressBar();
    jpb.setIndeterminate(false);
    jpb.setMaximum(max);
    panel.add(label);
    panel.add(jpb);
    frame.add(panel);
    frame.pack();
    frame.setSize(200,90);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    new PopulatingCardsWorker(jpb, max, label).execute();
}

程序最初调用GUI应用程序,然后运行数据库获取代码,如下所示。

public static void main(String args[]) {
    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new MagicTheGatheringUI().setVisible(true);
        }
    });
}

public MagicTheGatheringUI() {
    int i, size;

    colorRefinementFilter = "selected";
    try {
        my_list=new CardDatabase();
        my_list.sortByName(my_list.all_cards);
        my_list.populateSubArrays();
        size = my_list.all_cards.size();

        for(i = 0; i < size; i++)
        {
            namesList.addElement(my_list.all_cards.get(i).name);
        }
    } catch(Exception e) {
        System.out.println(e);
        System.exit(0);
    }
    initComponents();
}

swing worker 是在“my_list=new CardDatabase();”的创建过程中创建的。在那个班上,我有摇摆工人和摇摆工人应该监控的过程。

我目前在名为“populate_cards()”的方法中调用 swing worker,并使用以下代码创建 swing worker。 swing worker 应该监控 populate_cards() 方法中发生的事情。 swing worker 方法中的所有数据都只是暂时的,直到我更好地了解如何让它按照我想要的方式工作。

SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            go(1000);
        }
    });

我认为问题在于我在实际 GUI 的“invokeLater”方法中调用进度条。

我查看了以下问题以尝试解决我的问题。

How to add a progress bar?

Can a progress bar be used in a class outside main?

我也看过教程。

【问题讨论】:

  • 根据你的代码,我看不到你打电话的任何地方PopulatingCardsWorker.go
  • 我还要强调SwingWorker 支持progress 属性,该属性可以与PropertyChangeListener - demonstrated here 结合使用
  • 我很抱歉。我重读了这篇文章并进行了更多编辑以提供更多代码。目前,代码有几千行,所以我试图将显示的内容限制为仅显示相关信息。再次,对于忽略您要求的最后一部分,我深表歉意。
  • populate_cards 怎么称呼?您可以考虑提供一个runnable example 来演示工作流程和您当前的问题
  • Ummmm 我不确定提供一个可运行的例子对于这个程序来说有多可行。它相当大,需要花费大量时间将代码简化为详细说明我的问题的基本内容。要回答您的问题,populate_cards 是 CardDatabase 中的一种方法。因此,调用 GUI,然后在初始化组件之前,初始化数据库。初始化数据库时,会调用一个swing worker来监控正在初始化的数据库的进度。

标签: java user-interface progress-bar


【解决方案1】:

您的代码没问题。代码结束后progressBar(和gui本身)弹出的原因是在java中默认情况下,代码和gui运行在同一个线程上。因为代码的优先级高于 gui,所以所有代码都会先执行,然后 gui 会更新。

你应该在 "go" 方法中这样做:

new Thread(){
    public void run(){
       new PopulatingCardsWorker(jpb, max, label).execute();
    }
} start();

see that article for more information about threads

我是用手机接电话的,很抱歉写得不好。

Code and GUi threads

and from Wikipedia

last one

【讨论】:

  • 我使用了您的建议并遇到了一些错误。我查阅了有关线程的 Java 教程并了解了这一点。新线程(新可运行(){@Override public void run(){新PopulatingCardsWorker(jpb,最大,标签).execute();}}).start();但现在我收到“jpb、max 和 label 是从内部类中访问的局部变量;需要声明为 final”的错误。我以前见过这个错误,我也找不到解决这个问题的方法。想法?
  • 我实际上只是修复了这些错误,运行了代码并遇到了同样的问题 =/ 在它应该监控的代码完成并开始运行后会弹出进度条。是否有可能我在 OP 中提到的另一个可运行对象中调用此可运行对象?
  • 嗨@Brian,很抱歉这个错误,我在开始之前忘记了点。关于您遇到的另一个错误,您可以将所有方法(来自 JFrame)放入线程中的运行中。你解决了吗?
猜你喜欢
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多