JPanel 删除组件并添加一个新组件抵消新组件

JPanel removing component and adding a new one offsets the new component

我正在开发一个求解器,通过生成地形图来说明 Nelder Mead 算法。地图由 JPanel 组件直观地表示(我知道地图生成的效果不如我希望的那样干净,但这是另一个问题)。我拥有的其中一个按钮应该通过从容器 JPanel 中删除旧组件并添加新组件来生成新地图;然而,虽然它确实绘制了一个新地图,但它显示它偏移了组件高度的一半。以下是重生被击中前后的图像。

初始地图图片

点击重新生成按钮后,新地图显示在 y 偏移处

这是我的主要代码(canvas 对象扩展了 JPanel):

public void init() {
        frame = new JFrame("Nelder Mead");
        container = new JPanel();

        solveButton = new JButton("Solve");
        solveButton.setToolTipText("Solves the given Height Map using the Nelder Mead algorithm.");
        resetButton = new JButton("Reset");
        resetButton.setToolTipText("Resets the simplex to its initial position.");
        reconfigureButton = new JButton("Reconfigure");
        reconfigureButton.setToolTipText("Reconfigures the simplex's initial position.");
        regenerateButton = new JButton("Regenerate");
        regenerateButton.setToolTipText("Generates a new Height Map and a new simplex.");

        buttonPanel = new JPanel();
        buttonPanel.setBackground(Color.WHITE);
        buttonPanel.setPreferredSize(BUTTON_SIZE);
        buttonPanel.add(solveButton);
        buttonPanel.add(resetButton);
        buttonPanel.add(reconfigureButton);
        buttonPanel.add(regenerateButton);

        canvas = new Canvas(new HeightMap(CANVAS_WIDTH, CANVAS_HEIGHT, TILE_WIDTH, TILE_HEIGHT, ELEVATION_MAX, ELEVATION_MIN));
        canvas.setPreferredSize(CANVAS_SIZE);

        container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
        container.add(buttonPanel);
        container.add(canvas);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(container);
        frame.pack();
        frame.setVisible(true);
    }

    public void run() {
        init();

        regenerateButton.addActionListener(event -> {
            running = false;
            container.remove(canvas);
            canvas = new Canvas(new HeightMap(CANVAS_WIDTH, CANVAS_HEIGHT, TILE_WIDTH, TILE_HEIGHT, ELEVATION_MAX, ELEVATION_MIN));
            container.add(canvas);
            frame.revalidate();
        });
    }

如果有人能为我指出正确的方向,我将不胜感激,谢谢。

我能够将 camickr 关于 reset() 方法的提示应用到我的代码中,这解决了我的问题。建议是让所有组件编辑发生在组件 class 中,而不是尝试修改组件在 JPanel 中的存在方式。我还更改了 canvas 对象以扩展 JComponent。对于以后遇到此问题的任何人,这里是解决方案:

regenerateButton.addActionListener(event -> {
            running = false;
            canvas.regenerate(CANVAS_WIDTH, CANVAS_HEIGHT, TILE_WIDTH, TILE_HEIGHT, ELEVATION_MAX, ELEVATION_MIN);
        });

[编辑] regenerate() 修改 canvas 的 HeightMap 对象并调用 this.repaint()