Zman31337
Zman31337

Reputation: 33

JButtons acting up in paintComponent()

I am sorry about the non-descriptive title but I am not sure how to communicate the problems. For starters the JButtons every now and again are creating themselves multiple times in the same order that the loop should create them. Another issue I am having is that when I reposition them using the setLocation() method it creates new JButtons where I want them but also leaves the old ones where they are. I don't know if I just have to refresh the graphics or what is going on. Thanks for the help.

the array playerHand()is defined in the Player class and is 5 in length.

public void paintComponent(java.awt.Graphics g){
    setBackground(Color.GREEN);

    // create a Graphics2D object from the graphics object for drawing shape
    Graphics2D gr=(Graphics2D) g;

    for(int x=0;x<Player.hand.size();x++){
        Card c = Player.hand.get(x);                    //c = current element in array
        c.XCenter = 30 + 140*x;                         
        c.XCord = c.XCenter - 30;
        c.YCord = 0;


        //5 pixel thick pen
        gr.setStroke(new java.awt.BasicStroke(3));            
        gr.setColor(Color.black);                       //sets pen color to black
        gr.drawRect(c.XCord, c.YCord, c.cardWidth-1, c.cardHeight-1);          //draws card outline
        gr.setFont(new Font("Serif", Font.PLAIN, 18));

        gr.drawString(c.name, c.XCord+10, c.YCord+20);

        gr.drawString("Atk: ", c.XCord+10, c.YCord+60);
        gr.drawString(""+c.attack, c.XCord+60, c.YCord+60);

        gr.drawString("Def: ", c.XCord+10, c.YCord+80);
        gr.drawString(""+c.defence, c.XCord+60, c.YCord+80);

        gr.drawString("HP: ", c.XCord+10, c.YCord+100);
        gr.drawString(""+c.health, c.XCord+60, c.YCord+100);

        JButton button = new JButton(c.name);
        button.setSize(c.cardWidth, c.cardHeight);
        //button.setLocation(c.XCord, c.YCord);
        this.add(button);
        repaint();
    }
}   //end of paintComponent

Upvotes: 3

Views: 147

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

There are several problems (marked by "!!!!" comments) in your method below:

public void paintComponent(java.awt.Graphics g){
    setBackground(Color.GREEN); // !!!!
    Graphics2D gr=(Graphics2D) g;
    for(int x=0;x<Player.hand.size();x++){

        // .... etc ....

        JButton button = new JButton(c.name);  // !!!! yikes !!!!
        button.setSize(c.cardWidth, c.cardHeight);
        //button.setLocation(c.XCord, c.YCord);
        this.add(button);  // !!!! yikes !!!!
        repaint();  // !!!!
    }
}
  • Do not add components to GUI's in paintComponent(...). Never do this. Ever.
  • This method should be for drawing and drawing only and never for program logic or GUI building.
  • You do not have full control over when or if it will be called.
  • It needs to be as fast as possible so as not to make your program poorly responsive.
  • Avoid object creation within paintComponent(...) if possible.
  • Avoid file I/O in this method (though not a problem with your code above).
  • Don't call setBackground(...) in this method. Do that in the constructor or other method.
  • Never call repaint() from within this method.
  • Don't forget to call the super's paintComponent(g) method in your override.

To go over your problems:

For starters the JButtons every now and again are creating themselves multiple times in the same order that the loop should create them.

This is because you do not have control over when or how often paintComponent is called. The JVM may call it in response to information from the operating system about a dirty region, or the program may request a repaint, but for this reason, program logic and gui building should never be in this method.

Another issue I am having is that when I reposition them using the setLocation() method it creates new JButtons where I want them but also leaves the old ones where they are.

Quite likely you're seeing image remnants from your not calling the super's paintComponent method. By not doing this, you don't have the JPanel repaint itself and remove old image pixels that need to be replaced or refreshed.

I don't know if I just have to refresh the graphics or what is going on.

No, you need to change just about everything.

It looks like you have to re-think your GUI's program flow and logic and re-write a bit of code.

Upvotes: 5

Related Questions