gpt4 book ai didi

java - 如何在加载 Swing 构建 GUI 时更新/绘制 JProgressBar

转载 作者:搜寻专家 更新时间:2023-10-31 19:35:08 25 4
gpt4 key购买 nike

我有一个 GUI,在它运行的平台上构建/初始化非常繁重。因此我想在它初始化时更新进度。

我有一个未修饰的小 JDialog,其中包含一个 JLabel 和一个 JProgressBar,我想在初始化期间在特定位置更新它们,但是,因为事件调度 thead(根据 Swing 规则)用于构建/初始化 GUI,所以进度当然是等到EDT再次空闲(即初始化完成)后才会更新。

我已经使用“paintImmediately”重新绘制了 JProgressBar,但我似乎无法使其对 JLabel 和对话框本身正常工作。是否有任何简单的推荐/经过验证的方法来完成此操作?

干杯...

编辑:添加一个我正在尝试做的例子;当然,大大简化了。

private JLabel progressLabel;
private JProgressBar progressBar;

public static int main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showProgressDialog();
progressLabel.setText("construct 1");

constructSomeHeavyGUI();

progressLabel.setText("construct 2");
progressBar.setValue(33);

constructSomeMoreHeavyGUI();

progressLabel.setText("construct 3");
progressBar.setValue(67);

constructEvenMoreHeavyGUI();

progressLabel.setText("done");
progressBar.setValue(100);

hideProgressDialog();

showHeavyGUI();

}
});
}

调用 progressBar.setValue()/progressLabel.setText() 引起的重绘当然会在 EDT 繁忙时排队,结果在我们全部完成后重新绘制而不是一路更新..

最佳答案

我建议使用 SwingWorker ,然后您可以在美国东部时间正确更新 JProgressBar,而不会出现任何卡住或问题 Concurency in Swing ,

还有一个选项是使用 Runnable#thread,但是你必须将所有输出到 GUI 的包装到 invokeLater();

例如:

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("WRONG attempt to show Progress Bar");
JButton myAttempt = new JButton("BETTER 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();
}
}

编辑:

1) 你展示了另一个问题,为什么你在 Fly/Runtime 上创建大量顶级容器,只创建所需数量的容器并通过 removeAll() 重新使用它

2) here可能是你需要的,所有这些 JProgressBarsJTable非常易于访问和配置

3) 这是你的 paintImmediately() ,这就是为什么不在 JLabel 上绘制任何 Progress 的真正原因但使用 JProgressBar#setValue(int);
相反,

关于java - 如何在加载 Swing 构建 GUI 时更新/绘制 JProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7078764/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com