当前位置: 首页 > 面试题库 >

新线程JDialog中的JProgressBar

有耀
2023-03-14
问题内容

我想在新的JDialog中创建JProgressBar,它将与主逻辑处于不同的线程中。因此,我可以通过仅创建新的JDialog并通过处置JDialog完成该进度来开始不确定的进度。但这给了我很多时间,因为在出​​现JDialog之后,直到完成主线程(SwingUtilities)中的逻辑后,它才显示任何组件(包括JProgressBar)。

包含JDialog的线程:

package gui.progress;

public class ProgressThread extends Thread {
    private ProgressBar progressBar = null;

    public ProgressThread() {
        super();
    }

    @Override
    public void run() {
        progressBar = new ProgressBar(null);
        progressBar.setVisible(true);
    }

    public void stopThread() {
        progressBar.dispose();
    }
}

JProgressBar切换方法:

private static ProgressThread progressThread = null;
...
public static void toggleProcessBar() {
    if(progressThread == null) {
        progressThread = new ProgressThread();
        progressThread.start();
    } else {
        progressThread.stopThread();
        progressThread = null;
    }
}

问题答案:

但这给了我很多时间,因为在出​​现JDialog之后,直到完成主线程(SwingUtilities)中的逻辑后,它才显示任何组件(包括JProgressBar)。

您在Swing中存在并发问题,Swing是单线程的,所有更新必须在EventDispatchThread上完成,有两种方法

  • 易于使用Runnable#Thread,但必须将输出包装到Swing GUI中invokeLater

  • 使用SwingWorker,有关示例,请SwingWorker参见Oracle JProgressBar和SwingWorker教程

编辑

此代码模拟违反EDT的行为,也针对SwingWorker纠正了解决方法

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

public class TestProgressBar {

    private static void createAndShowUI() {
        JFrame frame = new JFrame("TestProgressBar");
        frame.getContentPane().add(new TestPBGui().getMainPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowUI();
            }
        });
    }

    private TestProgressBar() {
    }
}

class TestPBGui {

    private JPanel mainPanel = new JPanel();

    public TestPBGui() {
        JButton yourAttempt = new JButton("Your attempt to show Progress Bar");
        JButton myAttempt = new JButton("My attempt to show Progress Bar");
        yourAttempt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                yourAttemptActionPerformed();
            }
        });
        myAttempt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                myAttemptActionPerformed();
            }
        });
        mainPanel.add(yourAttempt);
        mainPanel.add(myAttempt);
    }

    private void yourAttemptActionPerformed() {
        Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
        JDialog progressDialog = new JDialog(thisWin, "Uploading...");
        JPanel contentPane = new JPanel();
        contentPane.setPreferredSize(new Dimension(300, 100));
        JProgressBar bar = new JProgressBar(0, 100);
        bar.setIndeterminate(true);
        contentPane.add(bar);
        progressDialog.setContentPane(contentPane);
        progressDialog.pack();
        progressDialog.setLocationRelativeTo(null);
        Task task = new Task("Your attempt");
        task.execute();
        progressDialog.setVisible(true);
        while (!task.isDone()) {
        }
        progressDialog.dispose();
    }

    private void myAttemptActionPerformed() {
        Window thisWin = SwingUtilities.getWindowAncestor(mainPanel);
        final JDialog progressDialog = new JDialog(thisWin, "Uploading...");
        JPanel contentPane = new JPanel();
        contentPane.setPreferredSize(new Dimension(300, 100));
        final JProgressBar bar = new JProgressBar(0, 100);
        bar.setIndeterminate(true);
        contentPane.add(bar);
        progressDialog.setContentPane(contentPane);
        progressDialog.pack();
        progressDialog.setLocationRelativeTo(null);
        final Task task = new Task("My attempt");
        task.addPropertyChangeListener(new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equalsIgnoreCase("progress")) {
                    int progress = task.getProgress();
                    if (progress == 0) {
                        bar.setIndeterminate(true);
                    } else {
                        bar.setIndeterminate(false);
                        bar.setValue(progress);
                        progressDialog.dispose();
                    }
                }
            }
        });
        task.execute();
        progressDialog.setVisible(true);
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }
}

class Task extends SwingWorker<Void, Void> {

    private static final long SLEEP_TIME = 4000;
    private String text;

    public Task(String text) {
        this.text = text;
    }

    @Override
    public Void doInBackground() {
        setProgress(0);
        try {
            Thread.sleep(SLEEP_TIME);// imitate a long-running task
        } catch (InterruptedException e) {
        }
        setProgress(100);
        return null;
    }

    @Override
    public void done() {
        System.out.println(text + " is done");
        Toolkit.getDefaultToolkit().beep();
    }
}


 类似资料:
  • 问题是这样的: 我有一个摆动应用程序正在运行,在某一点上,一个对话框需要插入用户名和密码并按“确定”。 我希望当用户按“确定”时,摆动应用程序按以下顺序执行: 打开“请稍候”JDialog 进行一些操作(最终显示一些其他JDialog或JOptionPane) 操作完成后,关闭“please wait”(请等待)JDialog 这是我在okButtonActionPerformed()中编写的代码

  • 我做了这段代码,我需要在屏幕上实时显示一些值,所以,我试着这样做,有人知道是怎么回事吗? 安卓显示器: java.lang.NullPointerException:尝试在Android.Widget.TextView.OnMeasure(TextView.java:7520)的Android.View.View.Measure(View.java:19917)的Android.View.View

  • 问题内容: 我刚刚开始进行android开发,并且更新UI确实使我很烦:/ 到目前为止,这是我一直在努力的工作- 它工作正常,但是每个人都说要在主线程中做图形,所以我正在尝试(但失败)将其传递给另一个线程。麻烦的是,我真的不知道怎么做,因为我从未真正使用过线程。 Google给出的有关使用Threads的示例似乎并不十分清楚,我也无法真正按照自己的意愿去做。我可以请某人在这里给我一个最基本的例子,

  • 特性: 可修改CSS来统一定制UI; 通过参数设置标题,高度,宽度,窗口显示的HTML内容; 一个页面同时只能显示一个窗口; 窗口显示需要指定一个页面上的对象做为窗口显示做置定位,这样窗口会出现在哪个东西的下面,就像下拉列表一样. 不能拖动(我们不需要这样的功能); 可以点击窗口之外的任意区域来关闭窗口,或是点右上角的关闭按钮. 演示地址: http://huacnlee.github.com/jdialog/

  • 以下是Sun创建线程的简单规则: 如果线程数小于corePoolSize,请创建新线程以运行新任务 为什么在队列已满时创建非核心线程?我不明白他们为什么这样做。为什么不在队列为空时创建非核心线程?

  • 问题内容: 我试图在这里理解代码,特别是匿名类 文章说 处理程序将更新代码作为主线程的一部分运行,从而避免了第二个线程的开销。 创建新的Runnable类是否应该创建新的第二个线程?除了能够将Runnable类传递给postAtTime之外,这里Runnable类的目的是什么? 谢谢 问题答案: 通常用于提供线程应运行的代码,但它本身与线程无关。它只是一个带有方法的对象。 在Android中,该类