java - 在运行时创建 JLabel : View in Swing does not update as intended

标签 java swing gridview model-view-controller jlabel

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

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

当我运行调试器时,我可以看到标签已创建并添加到父 View 中。但我在我的 View 中看不到标签。有什么想法吗?

//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?

标签的大小为 (0, 0),因此无需绘制任何内容。

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

所以基本代码是:

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

如果添加多个组件,则仅在添加所有组件后才执行 revalidate() 和 repaint()。

关于java - 在运行时创建 JLabel : View in Swing does not update as intended,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36557454/

相关文章:

java - 使用 Java Swing 进行网络爬行

javascript - 在 ASP Gridview 删除命令中使用 JavaScript 提示来存储 "Reason for Deletion"

JavaPoet 检查 TypeName 是否是 List 的实例

Java - 如何避免在 divide 和 cast to int 期间丢失精度?

java - 将文本换行到文本框中

java JLayeredPane 如何在 Window builder 生成的另一个面板前面添加 JPanel

wpf - 反转 WPF GridView 以将项目绑定(bind)到列而不是行

c# - 如何填充 GridView 异步

java - 使用 JUnit 和 Jersey Client 测试 JAX-RS 应用程序

java - 当我的编译器告诉我正在使用不安全或未经检查的操作时,这意味着什么?