Java Swing JPanel 不会重绘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2155351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swing JPanel won't repaint
提问by Aly
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. However the labels do not show up after the update method is called, below is the code for update:
我有一个扩展的简单对象JPanel
,当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. Once that was fixed the adding of new JLabel
s works fine. I also:
事实证明,HoleCardsPanel
没有正确添加到其父框架中。一旦解决了这个问题,添加 new JLabel
s 就可以正常工作了。我也:
- added the call to the
update()
method to the event dispatch thread usingSwingUtillities.invokeLater
- had to call
validate()
from the uppermost component (in this case theJFrame
) as Devon_C_Miller suggests in his answer.
- 将对该
update()
方法的调用添加到事件调度线程使用SwingUtillities.invokeLater
- 正如 Devon_C_Miller在他的回答中所建议的那样,必须
validate()
从最上面的组件(在本例中为JFrame
)调用。
回答by Philippe Carriere
Have you tried SetVisible() on the labels ?
你在标签上试过 SetVisible() 吗?
Have you tried to add the objets at initialisation without any update ? If they don't show up there, they will never show up.
您是否尝试在初始化时添加对象而不进行任何更新?如果他们不出现在那里,他们将永远不会出现。
回答by Chris Kannon
Try calling revalidate(); repaint is not what you want.
尝试调用 revalidate(); 重绘不是你想要的。
As per:
按照:
API Docs
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. If multiple components are being added, you can improve efficiency by calling validate only once, after all the components have been added.
API 文档
注意:如果组件已添加到已显示的容器中,则必须在该容器上调用 validate 以显示新组件。如果要添加多个组件,您可以在添加所有组件后仅调用一次 validate 来提高效率。
revalidate() is basically a invalidate() followed by a validate().
revalidate() 基本上是一个 invalidate() 后跟一个 validate()。
See thisquestion.....
看到这个问题.....
回答by trashgod
The call to validate()
should work, although revalidate()
may be sufficient; repaint()
should not be required. You might compare what you're doing to this examplethat does dynamic GridBagLayout
.
调用validate()
应该可以工作,尽管revalidate()
可能就足够了;repaint()
不应该被要求。您可以将您正在执行的操作与执行 dynamic 的示例进行比较GridBagLayout
。
回答by Carlos Blanco
You could try calling updateUI()
method.
你可以试试调用updateUI()
方法。
回答by Devon_C_Miller
It depends on what you want to happen and what layout managers are in use, but the basic rules are:
这取决于您想要发生的事情以及正在使用的布局管理器,但基本规则是:
Make sure
update
is called on the EDT. If it's not (SwingUtilities.isEventDispatchThread()
returns false) you will need to useSwingUtilities.invokeLater
to schedule the update on the EDT. For example:SwingUtilities.invokeLater(new Runnable() { public void run() { update(); }});
Call
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.Call
validate()
on the highestaffected component. This is probably the muddiest bit of Java's rendering cycle. The call toinvalidate
marks the component and all of its ancestorsas needing layout. The call tovalidate
performs the layout of the component and all of its descendants. One works "up" and the other works "down". You need to callvalidate
on the highest component in the tree that will be affected by your change.Also, calling validate on a top-level component (JWindow, JDialog, JFrame) will not necessarily resize that component. To make that happen, you'll need to call
pack()
orsetSize()
.If your changes alter the size or position of containers, The resized containers will repaint, but they will not erase the space the used tooccupy. Calling
repaint()
on the parent of the container will cause it to repaint the background, correcting the damage.
确保
update
在 EDT 上调用。如果不是(SwingUtilities.isEventDispatchThread()
返回 false),您将需要使用它SwingUtilities.invokeLater
来安排 EDT 上的更新。例如:SwingUtilities.invokeLater(new Runnable() { public void run() { update(); }});
打电话
invalidate()
。大多数更改组件的事情都会为您做到这一点。因此,只有在以下内容本身不起作用时才需要调用它。调用
validate()
上最高的受影响的组件。这可能是 Java 渲染周期中最混乱的部分。调用invalidate
将组件及其所有祖先标记为需要布局。调用validate
执行组件及其所有后代的布局。一个“向上”工作,另一个“向下”工作。您需要调用validate
树中将受您更改影响的最高组件。此外,在顶级组件(JWindow、JDialog、JFrame)上调用 validate 不一定会调整该组件的大小。要做到这一点,您需要调用
pack()
或setSize()
。如果您的更改改变了容器的大小或位置,调整大小的容器将重新绘制,但它们不会删除曾经占用的空间。调用
repaint()
容器的父级会导致它重新绘制背景,纠正损坏。
回答by Aly
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. 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
)
事实证明,HoleCardsPanel
wans 没有正确添加到其父框架,一旦修复了新JLabels
作品的添加就可以了。我添加调用update()
方法以event dispatch thread
使用SwingUtillities.invokeLater
予additionaly不得不打电话validate()
从最上面的组分(在这种情况下JFrame
)