-2

So I made tic-tac-toe GUI, and I found that the paint() method is being called twice when there is a mouse-click (check mouseClicked() event code). I have no idea- how's that happening and what should I do to avoid this issue.

import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 
public class tic_tac_toe_game extends JFrame implements MouseListener{ 
JPanel contentPane; 
JLabel box_1_1,box_1_2,box_1_3,box_2_1,box_2_2,box_2_3,box_3_1,box_3_2,box_3_3; //x, y coordinate 

static int turn = 1; // 1 is p1 turn 2 is p2 turn
static boolean win_state = false;
static boolean break_up = false;
static boolean cant_turn[][] = new boolean[3][3];
public tic_tac_toe_game() { 

    contentPane = new JPanel(); 
    contentPane.setLayout(null); 
    box_1_1 = new JLabel("T");
    box_1_2= new JLabel("T");
    box_1_3 = new JLabel("T");
    box_2_1= new JLabel("T");
    box_2_2 = new JLabel("T");
    box_2_3= new JLabel("T");
    box_3_1 = new JLabel("T");
    box_3_2= new JLabel("T");
    box_3_3 = new JLabel("T");

    //modify it in paint()


    //contentPane *NO* layout mnager  
    setContentPane(contentPane); 
    setSize(600,600); 
    setVisible(true); 
    setTitle("Tic tac toe game"); 
    setLayout(null); 


} 
public void paint(Graphics g) 
{ 


    g.drawLine(0, getHeight()/3*1, getWidth(), getHeight()/3); // 1, 2  lines haha (hor)
    g.drawLine(0, getHeight()/3*2, getWidth(), getHeight()/3*2);    //      (vertical) 
    g.drawLine(getWidth()/3*1, 0, getWidth()/3*1, getHeight()); // 1, 2  lines haha (hor)
    g.drawLine(getWidth()/3*2, 0, getWidth()/3*2, getHeight());  //(vertical);

    setup_UI();
    //box_1_1.set
} 
public void setup_UI()
{
    box_1_1.setFont(new Font("Serif",Font.BOLD,50)); 
    box_1_1.setBounds(getWidth()/3/3*1, getHeight()/3/3*1, 40, 40);
    box_1_1.addMouseListener(this);
    contentPane.add(box_1_1); 

    box_1_2.setFont(new Font("Serif",Font.BOLD,50)); 
    box_1_2.setBounds(getWidth()/3/3*1, getHeight()/3/3*4, 40, 40); 
    box_1_2.addMouseListener(this);
    contentPane.add(box_1_2); 

    box_1_3.setFont(new Font("Serif",Font.BOLD,50)); 
    box_1_3.setBounds(getWidth()/3/3*1, getHeight()/3/3*7, 40, 40); 
    box_1_3.addMouseListener(this);
    contentPane.add(box_1_3); 

    box_2_1.setFont(new Font("Serif",Font.BOLD,50)); 
    box_2_1.setBounds(getWidth()/3/3*4, getHeight()/3/3*1, 40, 40); 
    box_2_1.addMouseListener(this);
    contentPane.add(box_2_1); 

    box_2_2.setFont(new Font("Serif",Font.BOLD,50)); 
    box_2_2.setBounds(getWidth()/3/3*4, getHeight()/3/3*4, 40, 40); 
    box_2_2.addMouseListener(this);
    contentPane.add(box_2_2); 

    box_2_3.setFont(new Font("Serif",Font.BOLD,50)); 
    box_2_3.setBounds(getWidth()/3/3*4, getHeight()/3/3*7, 40, 40); 
    box_2_3.addMouseListener(this);
    contentPane.add(box_2_3); 

    box_3_1.setFont(new Font("Serif",Font.BOLD,50)); 
    box_3_1.setBounds(getWidth()/3/3*7, getHeight()/3/3*1, 40, 40); 
    box_3_1.addMouseListener(this);
    contentPane.add(box_3_1);

    box_3_2.setFont(new Font("Serif",Font.BOLD,50)); 
    box_3_2.setBounds(getWidth()/3/3*7, getHeight()/3/3*4, 40, 40); 
    box_3_2.addMouseListener(this);
    contentPane.add(box_3_2);

    box_3_3.setFont(new Font("Serif",Font.BOLD,50)); 
    box_3_3.setBounds(getWidth()/3/3*7, getHeight()/3/3*7, 40, 40); 
    box_3_3.addMouseListener(this);
    contentPane.add(box_3_3); 
} 
public static void main(String[] args) 
{ 
    tic_tac_toe_game tic = new tic_tac_toe_game(); 
    /*while(tic.win_state== false)
    {
    tic.whos_turn();
    //tic.rule(); // de termine if  player win or not
    }*/
} 
public void rule()
{
  //  if(box_1_1.equals('O') == true)
  //      System.out.append("Yes");
}
public void whos_turn()
{
    if(turn == 1 && break_up == false)
    {
    JOptionPane.showMessageDialog(null, "P1's turn ! ");

    break_up = true;

    }
    else if(turn == 2 && break_up == false)
    {
    JOptionPane.showMessageDialog(null, "P2's turn ! ");    

    break_up = true;
    }
}

@Override


public void mouseClicked(MouseEvent e) {        
    // TODO Auto-generated method stub
       System.out.print("I'm clicked");  //this one called twice

 }


@Override
public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

}
@Override
public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

}
@Override
public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub

}
@Override
public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub
}
}   
MoonBun
  • 4,322
  • 3
  • 37
  • 69
James Park
  • 165
  • 1
  • 2
  • 14
  • 1
    *"I have no idea how's that happen.."* The API decides when a component will be painted. It might need painting after being restored, coming to the front, being resized.. *"..and how should I do to avoid this issue"* It is not an issue & not something you can fix. The application must repaint itself when told to do so. If there is a complex part to the painting, paint it to a `BufferedImage` (then draw the image in the paint method). – Andrew Thompson Apr 10 '16 at 06:56
  • 4
    I'm voting to close this question as off-topic because the OP is trying to fix something that is not broken. – Andrew Thompson Apr 10 '16 at 06:58
  • Avoid using `null` layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify – MadProgrammer Apr 10 '16 at 07:18
  • You should also avoid overriding `paint`, generally but especially, of top level containers like `JFrame`. Have a look at [this](http://stackoverflow.com/questions/13734069/how-can-i-set-in-the-midst/13734319#13734319) for the most obvios reason why. See [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) and [Performing Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/) for more details – MadProgrammer Apr 10 '16 at 07:20
  • Painting can occur at any time for any number of reasons, many of which you don't control. Painting is for (custom) painting and nothing else and you should never change the state of the component during the paint process, otherwise you could set up an infinite loop of paint requests which could consume your CPU and bring your program to it's knees – MadProgrammer Apr 10 '16 at 07:21
  • @AndrewThompson "not broken so don't fix it" is a valid answer, that's no reason to close the question. – ivan_pozdeev Apr 10 '16 at 13:29

1 Answers1

1

Your paint method should only paint, and not do anything extra like call setup_UI. Call setup_UI in the constructor instead.

Note that your program is not thread-safe, you should not use the initial thread to create and manipulate swing components. Read https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html

Joni
  • 108,737
  • 14
  • 143
  • 193