在运行时创建 JLabel:Swing 中的视图未按预期更新

Create JLabels at Runtime: View in Swing does not update as intended

在我正在处理的项目中,我遇到了无法正确更新视图的问题。我已经提取了相关代码(自包含且可执行)。

点击更新按钮时,我希望屏幕上部的视图显示 PlayerDump-List 中保存的数据。因此,我首先通过调用 removeAll() 来清除视图。接下来,应该为每个 PlayerDump 创建一个新行,每行包含三个标签。

当我 运行 调试器时,我可以看到标签已创建并添加到父视图。但是我看不到标签。知道这是为什么吗?

//imports [...]

public class Main {
    public static void main(String[] args) {
        Random r = new Random();

        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());

        MultiplayerStatsTableView tv = new MultiplayerStatsTableView();
        frame.add(tv, BorderLayout.CENTER);

        Button b = new Button("Update");
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ArrayList<PlayerDump> l = new ArrayList<PlayerDump>();

                for (int i = 0; i < 5; i++) {
                    l.add(new PlayerDump("" + r.nextInt(), r.nextInt(), r.nextInt()));
                }

                tv.statsChanged(l);
            }
        });

        frame.add(b, BorderLayout.SOUTH);

        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setVisible(true);
    }
}

class MultiplayerStatsTableView extends JPanel {
    private JPanel dataPanel;

    public MultiplayerStatsTableView() {
        setLayout(new BorderLayout());

        dataPanel = new JPanel(new GridLayout(0, 3, 2, 2));
        add(dataPanel, BorderLayout.NORTH);
    }

    public synchronized void statsChanged(ArrayList<PlayerDump> playersDump) {
        for (PlayerDump dump : playersDump) {
            System.out.println(dump.toString());
        }

        Runnable r = new Runnable() {
            @Override
            public void run() {
                //delete old labels
                dataPanel.removeAll();

                //build column names
                dataPanel.add(new JLabel("Name"));
                dataPanel.add(new JLabel("Score"));
                dataPanel.add(new JLabel("Level"));

                //create and add new labels
                for (PlayerDump dump : playersDump) {

                    dataPanel.add(new JLabel(dump.getName()));
                    dataPanel.add(new JLabel("" + dump.getScore()));
                    dataPanel.add(new JLabel("" + dump.getLevel()));
                }
            }
        };

        EventQueue.invokeLater(r);
    }
}

class PlayerDump {
    protected String name;
    protected int score;
    protected int level;

    public PlayerDump(String name, int score, int level) {
        this.name = name;
    }

    //getters
    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

    public int getLevel() {
        return level;
    }

    //override
    @Override
    public String toString() {
        return "Player: " + name + ", Score: " + score + ", Level: " + level;
    }
}

When I run the debugger I can see that the labels are created and added to the parent view. But I cannot see the labels in my view. Any ideas why that is?

label的大小是(0, 0)所以没有什么可画的。

将组件添加到可见 GUI 时,您需要调用布局管理器,以便为组件指定大小和位置。

所以基本代码是:

panel.add(...);
panel.revalidate();
panel.repaint();

如果您添加多个组件,那么您只需在添加所有组件后执行 revalidate() 和 repaint()。