简体   繁体   English

Swing JPanel不会重绘

[英]Swing JPanel won't repaint

I have a simple object which extends JPanel , when the update() method is called on this object it it meant to add some labels to the panel and then repaint. 我有一个扩展JPanel的简单对象,当在此对象上调用update()方法时,它意味着向面板添加一些标签然后重新绘制。 However the labels do not show up after the update method is called, below is the code for update: 但是,调用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();
    }

any ideas? 有任何想法吗?

Thanks 谢谢

EDIT 编辑

solved: 解决了:

It turns out that the HoleCardsPanel wasn't adding to its parent frame properly. 事实证明, HoleCardsPanel没有正确添加到其父框架。 Once that was fixed the adding of new JLabel s works fine. 一旦修复了,添加新的JLabel可以了。 I also: 我也:

  • added the call to the update() method to the event dispatch thread using SwingUtillities.invokeLater 使用SwingUtillities.invokeLater将对update()方法的调用添加到事件派发线程
  • had to call validate() from the uppermost component (in this case the JFrame ) as Devon_C_Miller suggests in his answer . 必须从最上面的组件(在本例中为JFrame )调用validate() ,如Devon_C_Miller 在他的回答中所建议的那样

It depends on what you want to happen and what layout managers are in use, but the basic rules are: 这取决于您想要发生的事情以及正在使用的布局管理器,但基本规则是:

  1. Make sure update is called on the EDT. 确保在EDT上调用update If it's not ( SwingUtilities.isEventDispatchThread() returns false) you will need to use SwingUtilities.invokeLater to schedule the update on the EDT. 如果不是( SwingUtilities.isEventDispatchThread()返回false),则需要使用SwingUtilities.invokeLater来安排EDT上的更新。 For example: 例如:

     SwingUtilities.invokeLater(new Runnable() { public void run() { update(); }}); 
  2. Call invalidate() . 调用invalidate() Most things that change a component will do this for you. 大多数改变组件的东西都会为你做这件事。 So you only need to call this if the following does not work on its own. 所以如果以下内容不起作用,您只需要调用它。

  3. Call validate() on the highest affected component. 调用validate() 最高受影响的组件上。 This is probably the muddiest bit of Java's rendering cycle. 这可能是Java渲染周期中最混乱的部分。 The call to invalidate marks the component and all of its ancestors as needing layout. invalidate的调用将组件及其所有祖先标记为需要布局。 The call to validate performs the layout of the component and all of its descendants . validate的调用执行组件及其所有后代的布局。 One works "up" and the other works "down". 一个工作“向上”,另一个工作“向下”。 You need to call validate on the highest component in the tree that will be affected by your change. 您需要在树中受最大变化影响的最高组件上调用validate

    Also, calling validate on a top-level component (JWindow, JDialog, JFrame) will not necessarily resize that component. 此外,在顶级组件(JWindow,JDialog,JFrame)上调用validate不一定会调整该组件的大小。 To make that happen, you'll need to call pack() or setSize() . 要实现这一点,您需要调用pack()setSize()

  4. If your changes alter the size or position of containers, The resized containers will repaint, but they will not erase the space the used to occupy. 如果您的更改改变了容器的大小或位置,则已调整大小的容器将重新绘制,但它们不会擦除以前占用的空间。 Calling repaint() on the parent of the container will cause it to repaint the background, correcting the damage. 在容器的父级上调用repaint()将使其重新绘制背景,从而纠正损坏。

Try calling revalidate(); 尝试调用revalidate(); repaint is not what you want. 重画不是你想要的。

As per: 按照:

API Docs API文档

Note: If a component has been added to a container that has been displayed, validate must be called on that container to display the new component. 注意:如果已将组件添加到已显示的容器中,则必须在该容器上调用validate以显示新组件。 If multiple components are being added, you can improve efficiency by calling validate only once, after all the components have been added. 如果要添加多个组件,则可以在添加所有组件后仅调用一次验证来提高效率。

revalidate() is basically a invalidate() followed by a validate(). revalidate()基本上是invalidate(),后跟validate()。

See this question..... 看到这个问题.....

The call to validate() should work, although revalidate() may be sufficient; validate()的调用应该有效,尽管revalidate()可能就足够了; repaint() should not be required. 不应该要求repaint() You might compare what you're doing to this example that does dynamic GridBagLayout . 您可以将您正在做的事情与此动态GridBagLayout 示例进行比较。

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

Have you tried SetVisible() on the labels ? 你在标签上试过SetVisible()吗?

Have you tried to add the objets at initialisation without any update ? 您是否尝试在初始化时添加objets而不进行任何更新? If they don't show up there, they will never show up. 如果他们没有出现在那里,他们将永远不会出现。

It turns out that the HoleCardsPanel wansn't adding to its parent frame properly, once that was fixed the adding of new JLabels works fine. 事实证明, HoleCardsPanel没有正确地添加到其父框架,一旦修复了新的JLabels的添加工作正常。 I added call to the update() method to the event dispatch thread using SwingUtillities.invokeLater I additionaly had to call validate() from the uppermost component (in this case the JFrame ) 我使用SwingUtillities.invokeLater添加了对event dispatch threadupdate()方法的调用我另外必须从最上面的组件调用validate() (在本例中是JFrame

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM