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. However the labels do not show up after the update method is called, below is the code for 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:
- 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.
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 highest affected component. This is probably the muddiest bit of Java's rendering cycle. The call toinvalidate
marks the component and all of its ancestors as 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 to occupy. Calling
repaint()
on the parent of the container will cause it to repaint the background, correcting the damage.
Try calling revalidate(); repaint is not what you want.
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.
revalidate() is basically a invalidate() followed by a validate().
See this question.....
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 example that does dynamic GridBagLayout
.
You could try calling updateUI()
method.
Have you tried SetVisible() on the labels ?
Have you tried to add the objets at initialisation without any update ? 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. 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
)
精彩评论