Search code examples
javaswingjpaneljbuttonrepaint

JButton showing up in the wrong spot after repaint is called


I am trying to add a couple of JButton objects to my GUI program in Java and it is adding them to the JPanel (which is the main file of the program) but it is appearing in the incorrect spot. It is showing op at point [0, 0] and the action that is linked to it is happening at the correct spot. The rest of the elements on the panel are Images so the repaint method is called very often.

   private void init()
 {
      setLayout(null);
      setBackground(new Color(r, g, b));
      addMouseListener(this);
      addMouseMotionListener(this);

      setSize(681, 700);
      setPreferredSize(new Dimension(681, 700));
      Insets insets = getInsets();

      //wrong spot (click at [302, 5])
      undoButton = new JButton("Undo");
       undoButton.addActionListener(this);        //button 1
       undoButton.setActionCommand("undo");
       undoButton.setVisible(true);
      add(undoButton);

      pause = new JButton("pause");
      pause.addActionListener(this);
      pause.setActionCommand("pause");          //button 2
      pause.setVisible(true);
      pause.setEnabled(true);
      add(pause);

       Dimension size = undoButton.getPreferredSize();
       undoButton.setBounds(100 + insets.left, 15 + insets.top, size.width, size.height);

       size = pause.getPreferredSize();
       pause.setBounds(100 + insets.left + undoButton.getPreferredSize().width, 15 + insets.top, size.width, size.height);


       try{
            undoButton.setMultiClickThreshhold(500);
       }
       catch (Exception e)
       {}
       //... more code ...
}

   public void paint (Graphics g)
{
      //...paint the rest of the elements...

      undoButton.update(g);
      pause.update(g);
 }

The "pause" button is showing up at the origin on top of the undo button but the clicks is woking at the correct spots. The 2 buttons should be showing up where the blue box is and all of the other cards are Images. enter image description here


Solution

  • You should not be overriding paint, you should be overriding paintComponent. If your components have already been added to the panel, they will update themselves:

    public void paintComponent(Graphics g)
    {
          super.paintComponent(g);
          //...paint the rest of the elements...
    
          //undoButton.update(g); BAD!
          //pause.update(g); BAD!
     }
    

    You don't have to worry about how the buttons get updated, the panel will handle that for you if you use it properly. Also do not use setLayout(null). We have layout managers for a reason, use one that has the features you need or write your own.