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

时间:2016-04-11 19:21:43

标签: java swing gridview model-view-controller jlabel

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

当点击更新按钮时,我希望屏幕上方的视图显示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;
    }
}

1 个答案:

答案 0 :(得分:3)

  

当我运行调试器时,我可以看到标签已创建并添加到父视图中。但在我看来,我看不到标签。任何想法为什么会这样?

标签的大小为(0,0),因此无需绘画。

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

所以基本代码是:

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

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