我正在将 JavaFX UI 恢复为 Swing。 在用户界面中,我有一个带有进度条的任务表。当任务的长度不确定时,我想使用不确定的进度条。不幸的是,我不知道如何在表格内获得不确定的进度条动画。
GPT-4 在搜索这个网站时非常“有帮助”,为我提供了各种不起作用的示例。
我在下面构建了一个示例。它绘制一个带有动画不确定进度条的 UI。每 5 秒,它就会向表格添加一个栏 - 在新栏和顶部动画栏之间交替。
表格中没有任何动画。此外,如果我将顶部的栏添加到表格中,它也会在顶部停止动画。
发生什么事了?
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
@SuppressWarnings("serial")
public class TestSwing extends JPanel implements TableCellRenderer
{
String[] header = {"Progress"};
DefaultTableModel tableModel = new DefaultTableModel(null, header) {
@Override
public Class<?> getColumnClass(int col) {
return getValueAt(0, col).getClass();
}
};
JTable table = new JTable(tableModel);
JProgressBar bar = new JProgressBar();
public TestSwing()
{
bar.setIndeterminate(true);
TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(0).setCellRenderer(this);
setLayout(new BorderLayout());
add(bar, BorderLayout.NORTH);
JScrollPane scroll = new JScrollPane(table);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
add(scroll, BorderLayout.CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
return bar;
}
protected void update()
{
while (true) {
try {
Thread.sleep(5000);
} catch (Exception e) {};
EventQueue.invokeLater(() -> {
tableModel.addRow(new Object[] {Boolean.TRUE});
});
}
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TestSwing list = new TestSwing();
f.add(list);
f.setSize(new Dimension(300, 500));
f.setLocationRelativeTo(null);
f.setVisible(true);
Thread updater = new Thread(() -> list.update(), "List Updater");
updater.setDaemon(true);
updater.start();
}
});
}
}
这个问题在此网站上出现过几次: 我尝试按照一个已接受的答案的建议更新表模型。 我尝试按照另一个人的建议重新绘制表格。 我什至尝试让 TableCellRenderer 针对不确定的行返回不同的条形图作为第三个可接受的答案。
最后,在构建这个玩具问题时,我意识到一旦添加到表格中,即使是一个正在运行的不确定条也会停止动画。
如果这适用于您的虚拟机,请告诉我您正在使用什么。它对我的任何一个都不起作用。
我无法理解您发布的代码。
我继续创建了这个 GUI。
一般来说,您首先创建 GUI,然后修改 GUI 的状态。永远不要在 Swing GUI 中使用
Thread.sleep
。始终使用 Swing Timer
。
Oracle 有一个有用的教程,使用 Swing 创建 GUI。跳过使用 NetBeans IDE 学习 Swing 部分。
所有 Swing 应用程序都必须以调用SwingUtilities
invokeLater
方法开始。此方法确保 Swing 组件在Event Dispatch Thread 上创建并执行。 这是我想出的代码。
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class JProgressBarTests implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JProgressBarTests());
}
private int listIndex;
private JProgressBar[] list;
public JProgressBarTests() {
this.listIndex = 0;
this.list = new JProgressBar[10];
}
@Override
public void run() {
JFrame frame = new JFrame("JProgressBar Tests");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createProgressPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
Timer timer = new Timer(5000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
list[listIndex]
.setIndeterminate(!list[listIndex].isIndeterminate());
listIndex++;
listIndex = listIndex % list.length;
}
});
timer.setInitialDelay(0);
timer.start();
}
private JPanel createProgressPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JLabel label = new JLabel("Progress");
panel.add(label, BorderLayout.NORTH);
JPanel innerPanel = new JPanel(new GridLayout(0, 1, 5, 5));
for (int index = 0; index < list.length; index++) {
list[index] = new JProgressBar();
innerPanel.add(list[index]);
}
panel.add(innerPanel, BorderLayout.CENTER);
return panel;
}
}