【发布时间】:2020-03-05 16:20:23
【问题描述】:
你好堆栈交换器,
Java Swing 中的进度条有问题。我认为我的困惑源于我对线程和 Swing 事件队列的了解不足(我不太了解 java 线程,以及 AWTEventQueue 上发生的确切情况,尽管我通常了解多线程是什么)。
上下文是按下JButton 以开始长时间计算。在计算开始之前,我在JFrame 中创建了一个进度条,我原以为会绘制它,但事实并非如此。框架出现,但它只是灰色的。在本例中,按钮上写有“clickMe”。
在“clickMe”动作监听器中,我首先在“运行”的子任务中创建并显示JFrame(我不清楚何时安排TBH)。然后,我调用doTask(),它与动作侦听器在同一个线程中运行(我认为是AWTEventThread??)。 doTask() 运行,将数字打印到控制台。与doTask() 输出混合的是进度条的迭代计数(从动作侦听器启动时开始makeProgressBar())。
因此,从输出看,进度条和AWTEventThread 都在运行,但JProgressBar GUI 中设置的值从未更新。
如何更改我的代码以更新 GUI?我尝试了解JProgressBar 教程并在网上搜索,但我认为我的问题更多是对 Java 任务的概念性理解。
这是我的代码:
package problemclass;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
public class ProblemClass
{
void progressBarButtonClick()
{
JFrame buttonInAFrame = new JFrame();
JPanel buttonInAFramePanel = new JPanel();
JButton clickMe = new JButton("Click me!");
buttonInAFramePanel.add(clickMe);
clickMe.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
JFrame progBarFrame = makeProgressBar();
doTask();
progBarFrame.dispose();
}
});
buttonInAFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
buttonInAFrame.add(buttonInAFramePanel);
buttonInAFrame.pack();
buttonInAFrame.setVisible(true);
}
private void doTask()
{
for(int i = 0; i < 20000; i++)
{
if (i % 100 == 0)
{
System.out.println("TASK iteration " + i);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e) {}
}
}
}
private JFrame makeProgressBar()
{
JFrame progBarFrame = new JFrame();
JPanel progBarPanel = new JPanel();
JProgressBar progressBar = new JProgressBar();
progBarPanel.add(progressBar);
progressBar.setValue(0);
progressBar.setStringPainted(true);
progressBar.setIndeterminate(true);
new Thread(new Runnable()
{
public void run()
{
for (int i = 0; i <= 100; i++)
{
final int j = i;
System.out.println("Progress Iteration " + j);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
progressBar.setValue(j);
}
});
try
{
java.lang.Thread.sleep(100);
}
catch(Exception e) { }
}
}
}).start();
progBarFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
progBarFrame.add(progBarPanel);
progBarFrame.pack();
progBarFrame.setVisible(true);
return progBarFrame;
}
public static void main(String[] args)
{
EventQueue.invokeLater(() ->
{
new ProblemClass().progressBarButtonClick();
});
}
}
【问题讨论】:
标签: java multithreading swing jprogressbar