0

I have a display that just shows a score on a page:

for example: JIMBOB Total Score: 22

When a point is scored an event is triggered that updates the score and redraws the new score on the page:

public void showScore(String username, int score)
{
    contentPane.remove(layout.getLayoutComponent(BorderLayout.CENTER));
    score.setText("<html>" + username + "<br/>Total Hits: " + totalHits + "</html>");
    contentPane.add(score, BorderLayout.CENTER);
    frame.pack();
    frame.setVisible(true);
}

Every time a point is scored this function is called, it removes the old score message adds an new one then packs and redraws.

The problem is that the window flickers when drawing the updated frame. And it seems for a split second to be displaying the info unformatted

contentPane is a Container and frame is a JFrame

c_breeez
  • 338
  • 3
  • 13

2 Answers2

2

Invoking pack() will completely re-render the JFrame, a top-level, heavyweight container owned by the host platform. Instead, update the JComponent used to display the revised score. A complete example is cited here. Excerpted form RCStatus,

public class RCStatus extends JPanel implements Observer {

    /** Update the game's status display. */
    public void update(Observable model, Object arg) {
        // invoke setText() here
    }
}

See this answer for more on the observer pattern.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Hi thanks for the answer, i ended up just using revalidate() then repaint(), instead of pack() and it solved my problems – c_breeez Aug 04 '14 at 21:44
1

First of all, I would recommend to take a look at how to use JPanels and other GUI components in Swing. You could use a JPanel to be added to the contentPane of your JFrame. Add a desired LayoutManager that is fitting for your need and use it to position a JLabel according to your wishes.

When you call your showScore() method, use setText(String text) on a JLabel instead of the int score that you supply as parameter.

In order to set the text using a String, you need to transform your int score. You can do either of the following two things (but use the first option):

label.setText(String.valueOf(score));
label.setText("" + score);

If you want the score label to appear or disappear, add/ remove it from the JPanel that you added to the JFrame. After adding it, call setText() on the label to display the score. Then, since you reset the text of the label, you should call repaint() on the JPanel. If you choose to add/ remove the JLabel instead of just changing its text you should also call revalidate() on the JPanel.

So all in all the function should look something like this (this is incomplete), assuming totalHits is actually your score.

// declare instance fields before constructor
// both variables are reachable by showScore() 
private JPanel scorePanel; 
private JLabel scoreLabel;

// in constructor of your class
scorePanel = new JPanel(); // initialize the JPanel
scorePanel.setLayout(new BorderLayout()); // give it a layout

scoreLabel = new JLabel(); // initialize the label

frame.add(scorePanel); // add JPanel to your JFrame

// method obviously outside constructor
public void showScore(String username, int score)
{
    // clear the JPanel that contains the JLabel to remove it
    scorePanel.removeAll();
    scoreLabel.setText("<html>" + username + "<br/>Total Hits: " + String.valueOf(score) + "</html>");
    scorePanel.add(label, BorderLayout.CENTER);

    scorePanel.revalidate();
    scorePanel.repaint();
}

You could also declare and initialize the JPanel and JLabel in the showScore() method, making it more local. But then you would also need to call pack() on the JFrame and clear the previous JPanel from it every time you call the function.

.

ChrisK
  • 158
  • 1
  • 13
  • WOW, thanks a lot brilliant informative and concise answer. Using revalidate(); and repaint(); on my Container (instead of frame.pack()) solved the issue completely. Is there an advantage to using a JPane over a Container? What is the advantage of using String.valueOf(totalHits) instead of just + totalHits? – c_breeez Aug 04 '14 at 18:10