一个面板 JFrame 称为 WatchPanel extends JPanel 使用的 GroupLayout 并包含一个 WatchListPanel extends JPanel. 。这 WatchListPanel 使用 null LayoutManager 并包含几个实例 WatchItemPanel extends JPanel. 。这 WatchItemPanel 用一个 GridBagLayout.

当我加载框架并实例化时 WatchPanel, ,我预加载 WatchListPanel 三个 WatchItemPanel 带有数据的实例。这些工作正常。我的实现使这些实现可以通过拖动和掉落来重新排序(因此 null 布局),这也有效。在 WatchPanel 是添加新手表的按钮,它可以自己弹出一个新面板 JFrame 可以添加手表的地方。在此新面板上按下“保存”按钮时,它将新手表添加到 WatchPanel, ,滴入 WatchListPanel 并关闭 JFrame 用于添加新手表。

问题是当这个新的时候 WatchItemPanel 添加,除非我调整大小,否则它不会被涂漆 JFrame 包含 WatchPanel. 。我可以通过Drag-n-Drop与它进行互动。我什至可以拖动特定的面板 - 但它是空白的。我调整大小的那一刻 WatchPanel, ,它出现并正确绘制。

现在,我已经覆盖了 setBounds 方法开 WatchListPanel 打电话 setSizerepaint 在每个 WatchItemPanel 列表中的实例,但我在打电话 setBoundsrepaint 在新 WatchItemPanel 我已经添加了。我尝试添加 repaintinvalidate 在每个可能的地方打电话,也许我错过了一些东西,但没有运气。我绝对添加了 WatchItemPanelWatchListPanel 并打电话 setBounds, setVisible(true), , 和 repaint 在新面板上。

这里有 addWatchupdatePositionsWatchListPanel:

public void addWatch(Watch watch) {
    WatchItemPanel watchPanel = new WatchItemPanel(watch);
    synchronized (this.watches) {
        this.watches.add(watch);
    }
    this.watchPanels.put(watch, watchPanel);
    this.add(watchPanel);
    watchPanel.setOpaque(false);
    watchPanel.setForeground(this.getForeground());
    watchPanel.setBackground(this.getBackground());
    watchPanel.setVisible(true);
    watchPanel.setSize(this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
    for (MouseListener l: this.mouseListeners)
        watchPanel.addMouseListener(l);
    for (MouseMotionListener l: this.mouseMotionListeners)
        watchPanel.addMouseMotionListener(l);
    this.updatePositions();
}

private void updatePositions() {
    int count = 0;
    synchronized (this.watches) {
        for (Watch watch: this.watches) {
            if ((this.selectedWatchPanel != null) && (count == this.selectedWatchPanelPosition))
                count++;
            WatchItemPanel panel = this.watchPanels.get(watch);
            if (panel == this.selectedWatchPanel)
                continue;
            panel.setBounds(0, count * WatchItemPanel.PANEL_HEIGHT, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
            count++;
        }
    }
    if (this.selectedWatchPanel != null)
        this.selectedWatchPanel.setBounds(0, (this.selectedWatchPanelPosition * WatchItemPanel.PANEL_HEIGHT) + this.selectedWatchPanelDragOffset, this.getWidth(), WatchItemPanel.PANEL_HEIGHT);
    this.repaint();
}

这是 setBounds 方法开启 WatchListPanel:

@Override
public void setBounds(Rectangle r) {
    super.setBounds(r);
    for (WatchItemPanel panel: this.watchPanels.values()) {
        panel.setSize(r.width, WatchItemPanel.PANEL_HEIGHT);
        panel.repaint();
    }
}

@Override
public void setBounds(int x, int y, int width, int height) {
    super.setBounds(x, y, width, height);
    for (WatchItemPanel panel: this.watchPanels.values()) {
        panel.setSize(width, WatchItemPanel.PANEL_HEIGHT);
        panel.repaint();
    }
}

这里的另一个信息 - 所有四个面板都在绘制。我覆盖了 paintComponent 在里面 WatchItemPanel 并添加 System.out.println 并得到了这个结果:

WatchItemPanel[,0,66,366x22,invalid,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,44,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,22,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]
WatchItemPanel[,0,0,366x22,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777219,maximumSize=,minimumSize=,preferredSize=]

面板中的那个额外的“无效”列是什么?当我调整大小 WatchPanel “无效”消失了。不过,它看起来像一个额外的专栏。其他线上没有相应的无效值。 (这是默认 JPanel.toString() 输出包装名称已删除。

有帮助吗?

解决方案

添加组件后,请致电 this.revalidate(). 。这会导致标记容器以重新分配其组件。一旦添加了这条代码,它就可以完美地工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top