11

我有一个简单的对象 extends JPanel,当update()在这个对象上调用该方法时,它意味着向面板添加一些标签,然后重新绘制。但是调用更新方法后标签不会显示,下面是更新代码:

public void update(){
        GridBagConstraints constraints = new GridBagConstraints();

        if(cardsHidden){
            for(int i = 0; i < 2; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(PlayingCards.cardImages[PlayingCards.CARD_BACK_INDEX]);
                add(card, constraints);
            }
        }
        else{
            Card[] holeCards = player.getHoleCards();
            for(int i = 0; i < holeCards.length; i++){
                constraints.gridx = i;
                constraints.gridy = 0;
                JLabel card = new JLabel(holeCards[i].getImageIcon());
                add(card, constraints); 
            }
        }

        validate();
        repaint();
    }

有任何想法吗?

谢谢

编辑

解决了:

事实证明,HoleCardsPanel没有正确添加到其父框架。一旦解决了这个问题,添加 new JLabels 就可以了。我也:

  • 使用方法将调用添加update()到事件调度线程SwingUtillities.invokeLater
  • 正如 Devon_C_Miller在他的回答中所建议的那样,必须validate()从最上面的组件(在本例中为)调用。JFrame
4

6 回答 6

25

这取决于您想要发生的事情以及正在使用的布局管理器,但基本规则是:

  1. 确保update在 EDT 上被调用。如果不是(SwingUtilities.isEventDispatchThread()返回 false),您将需要SwingUtilities.invokeLater在 EDT 上安排更新。例如:

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            update();
        }});
    
  2. 打电话invalidate()。大多数改变组件的事情都会为你做这件事。因此,如果以下内容无法单独运行,您只需要调用它。

  3. 调用受validate()影响最大的组件。这可能是 Java 渲染周期中最混乱的部分。调用invalidate将组件及其所有祖先标记为需要布局。调用validate执行组件及其所有后代的布局。一个“向上”工作,另一个“向下”工作。您需要调用validate树中将受您的更改影响的最高组件。

    此外,在顶级组件(JWindow、JDialog、JFrame)上调用 validate 不一定会调整该组件的大小。要做到这一点,您需要调用pack()setSize()

  4. 如果您的更改改变了容器的大小或位置,则调整大小的容器将重新绘制,但它们不会擦除曾经占用的空间。调用repaint()容器的父级将导致它重新绘制背景,纠正损坏。

于 2010-01-28T20:36:15.573 回答
17

尝试调用 revalidate(); 重绘不是你想要的。

按照:

API 文档

注意:如果组件已添加到已显示的容器中,则必须在该容器上调用 validate 以显示新组件。如果要添加多个组件,您可以通过在添加所有组件后仅调用一次 validate 来提高效率。

revalidate() 基本上是一个 invalidate() 后跟一个 validate()。

看到这个问题......

于 2010-01-28T15:11:36.183 回答
5

调用validate()应该起作用,尽管revalidate()可能就足够了;repaint()不应该是必需的。您可以将您正在做的事情与这个执行 dynamic的示例GridBagLayout进行比较。

于 2010-01-28T19:18:47.890 回答
2

您可以尝试调用updateUI()方法。

于 2010-01-28T19:50:29.110 回答
0

您是否在标签上尝试过 SetVisible() ?

您是否尝试在初始化时添加对象而不进行任何更新?如果他们不出现在那里,他们将永远不会出现。

于 2010-01-28T15:05:56.630 回答
0

事实证明,HoleCardsPanelwansn 没有正确添加到其父框架,一旦修复了新JLabels作品的添加就可以了。我将对该update()方法的调用添加到了event dispatch thread使用中SwingUtillities.invokeLater,我还必须validate()从最上面的组件调用(在本例中为JFrame

于 2010-01-29T12:39:13.403 回答