为什么我的新组件不显示在空布局管理器中?

时间:2010-09-13 15:26:40

标签: java swing null-layout-manager

JFrame中有一个名为WatchPanel extends JPanel的小组使用GroupLayout并包含WatchListPanel extends JPanelWatchListPanel使用null LayoutManager并包含WatchItemPanel extends JPanel的多个实例。 WatchItemPanel使用GridBagLayout列出其内容。

当我加载框架并实例化WatchPanel时,我使用数据预加载WatchListPanel三个WatchItemPanel个实例。这些工作正常。我的实现允许通过拖放(因此null布局)重新排序这些,并且也可以。 WatchPanel上有一个添加新手表的按钮,可在其自己的JFrame中弹出一个可添加手表的新面板。在此新面板上按下“保存”按钮后,它会将新手表添加到WatchPanel,然后向WatchListPanel逐渐进入,并关闭JFrame以添加新手表。

问题在于,添加此新WatchItemPanel时,除非我调整包含JFrame的{​​{1}}的大小,否则不会对其进行绘制。我可以通过拖放来与它进行交互。我甚至可以拖动那个特定的面板 - 但它是空白的。当我调整WatchPanel的大小时,它会显示并正确绘制。

现在,我已覆盖WatchPanel上的setBounds方法,在列表中的每个WatchListPanel个实例上调用setSizerepaint,但我我在添加它时已在新WatchItemPanel上调用setBoundsrepaint。我尝试在每个可以想象的地方添加WatchItemPanelrepaint来电,以为我可能错过了一些东西,但没有运气。我绝对已将invalidate添加到WatchItemPanel,并在新面板上调用WatchListPanelsetBoundssetVisible(true)

以下是repaint上的addWatchupdatePositions方法:

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();
}

以下是WatchListPanel上的setBounds方法:

@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();
    }
}

这里的另一条信息 - 正在绘制所有四个面板。我在WatchListPanel中覆盖paintComponent并添加了WatchItemPanel并获得了此结果:

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=]

面板中那个额外的“无效”栏是什么?当我调整System.out.println的大小时,“无效”就会消失。不过,它看起来像一个额外的列。其他行上没有相应的非无效值。 (这是删除包名称的默认WatchPanel输出。

1 个答案:

答案 0 :(得分:0)

添加组件后,请致电this.revalidate()。这会导致容器被标记为重新布局其组件。一旦添加了这行代码,它就能完美运行。