为什么向 JTable 添加不确定的 JProgressBar 会杀死动画?

问题描述 投票:0回答:1

我正在将 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 针对不确定的行返回不同的条形图作为第三个可接受的答案。

最后,在构建这个玩具问题时,我意识到一旦添加到表格中,即使是一个正在运行的不确定条也会停止动画。

如果这适用于您的虚拟机,请告诉我您正在使用什么。它对我的任何一个都不起作用。

java swing jtable jprogressbar
1个回答
0
投票

我无法理解您发布的代码。

我继续创建了这个 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; } }
    
© www.soinside.com 2019 - 2024. All rights reserved.