1

I have looked all round, and no one seems to have an answer for me. I have a JPanel where I add/remove labels from it while it;s running. The problem is that every time I add a new label to it I have to revalidate() it so the new label shows up. Every time I revalidate(), it I get a very annoying flicker, and all my labels ghost up to the top of my window for a millisecond then return to what they were doing. The only time I call revalidate() is after I add a label; I do not change the paint method or anything only did

public void paintComponent(Graphics page)
{
    super.paintComponent(page);
}

so that my page would not look bad. I could really use some help on this. I've made a asteroids game using JFrame, Jlabel and Jpanel game; it work great, but this flickering and component "ghosting quickly ghosting to top of panel" is just unbearable, and I know for a fact this is the revalidate() method.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Elton
  • 83
  • 7
  • for information, i have a label that represents a ship, bullets, and asteroids, i add and remove them to my panel as they are used shot or run out of life. using the add(component); and remove(conponent); then after i add i revalidate. – Elton Feb 16 '13 at 10:30

4 Answers4

2

When I was having problems with filckering Swing components it turned out to be concurrency issues. Since you are doing a game, which means you are doing animation it may be the case here.

Take care to modify Swing components only from AWT-EVENT thread. Either use SwingUtilities.invokeLater or do your animation using javax.swing.Timer.

jb.
  • 23,300
  • 18
  • 98
  • 136
2

As a concrete example, Asteroids doesn't flicker at all. Here are a few reasons:

  • It runs on the event dispatch thread.

  • It uses JPanel, which is double buffered by default.

  • It paces the animation using javax.swing.Timer, updating the game's model in actionPerformed().

  • It overrides paintComponent(), but can safely omit super.paintComponent() because the action listener repaints the entire panel.

  • The listener calls paintImmediately() to avoid any potential delay; substitute repaint() to see if there's any difference on your platform.

Addendum: As shown in this counter-example, revalidate() does not cause flickering. Instead of replacing labels, update the label's icon, as shown here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

Have you considered reusing them - i.e. using setVisible(false) when they're not needed?

Not sure if adding and removing labels is the best way of achieving what you want for a game. I'd personally be tempted to manage the drawing myself.

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58
  • i think im going to try this, i am still amateur coder so this seems simplest to me, thanks for the feed back guys. – Elton Feb 16 '13 at 19:00
2

Using labels (or generally GUI components) to represent quickly animating, dynamically created/moved objects is not practical. Its like using a car to drive from the living room to the kitchen.

The Swing components come with a lot of nice features, e.g. they can determine the space they require and a layout manager can use that to automatically place them nicely. Unfortunately for a game, you neither need all the nice stuff, nor do you want to pay the processing overhead involved with it. Matters are further complicated by swings multi-platform capabilities which mandate that each component has a peer component (the peer deals with rendering the component to the active look).

To solve this, you do not represent individual game objects as swing components. Instead you use a single swing component (usually JPanel) as a canvas to paint your game objects on to. You simply call repaint() for that JPanel periodically (e.g. 30 or 60 times a second). Of course you will override paintComponent() on the JPanel to do paint all the game objects using your own code.

Edit: To outline how you do your own rendering

You need to decide how to organize your game related objects. A very simple skeleton could look like this (getters/setters omitted):

public class GameObject {
    public int x;
    public int y;
    public Image image;
}

In practice this class will have additional members (like a behavior that controls how the object moves, and maybe some states/counters for animation). It may also be abstract with a concrete subclass for each possible behavior (like ship, asteroid and bullet). All instances of GameObject are managed in some kind of collection, I assume you use a List.

When implementing the paintComponent it comes down to just loop through the list and render each objects's image:

public void paintComponent(Graphics g) {
    List<GameObject> list = ... // however you obtain it in your game
    for (GameObject gobject : list) {
        g.drawImage(gobject.image, gobject.x, gobject.y, (ImageObserver) null);
    }
}

More elaborate games may order the gameobjects to get control of how game objects overlap each other. But in principle its incredibly simple.

Durandal
  • 19,919
  • 4
  • 36
  • 70
  • the only problem which i dont know how to get around because im a noob is that each thing i.e bullet, asteroid and ship, there are a good amount of things i dont know how to represent as graphics. – Elton Feb 16 '13 at 19:03
  • @Elton I added some brief description how you create your own game objects and render them – Durandal Feb 18 '13 at 13:40