Jessica W
Jessica W

Reputation: 21

JButton only appears on mouse over?

Here is my code: I took out some stuff that I felt wasn't necessary. I might've took out some brackets too, but I'm just trying to show the content I have.

What happens is, when I run the program, the background image paints (it's a PNG in resources), and only ONE button appears (my PLAY button), which is the first button - it's auto-selected.

I actually have four buttons, but I've only included PLAY and INSTRUCTIONS in my code. The other three don't show up unless I mouse over them. I know it's probably something weird with the paint() method, but I don't know how to fix it.

If I select a different button and minimize the window, then open it again, that selected button is the only one that appears. I have to mouse over to get the other buttons to appear.

I've added super.paint() to the paint method too, and I get all my buttons, but the background is grey.

I think the problem is super.paint() paints all my buttons, and g.drawImage(bg, 0, 0, null) only paints my background, and I can't do one without painting over the other.

Sorry, if this was a mess. I'm new at Java, and I have trouble articulating what I'm trying to say.

public class MainMenu extends JFrame {

    private JPanel contentPane;

    /**
     * Launch the application.
     */

    //variables
    public static Image bg;
    
    public static void main(String[] args) {

        MainMenu mainFrame = new MainMenu();
        mainFrame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        mainFrame.setResizable(false);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setTitle ("Zumby");
        mainFrame.setLayout(null);
        
        // Loads the background image and stores in bg object.
        try {
            bg = ImageIO.read(new File("zumby.png"));
        } catch (IOException e) {
        }
        mainFrame.setVisible(true);
    }
                
    /**
     * Overrides the paint method.
     * MONDAY
     */
     public void paint(Graphics g)
     {
        // Draws the img to the BackgroundPanel.
        System.out.println("paint");
        g.drawImage(bg, 0, 0, null);
     }
     
    /**
     */
    public MainMenu() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 800, 500);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setOpaque(false);
        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        //create buttons
        JButton btnPlay = new JButton("PLAY");
        btnPlay.setBackground(Color.BLACK);
        btnPlay.setForeground(Color.WHITE);
        btnPlay.setFont(font);
        btnPlay.setBorder(border);
        btnPlay.setFocusPainted(false);
        
        //if "Play" is clicked
        
        btnPlay.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent click) {
                setVisible(false);
                new GamePlay(); //opens up GamePlay window
            }
        });
        btnPlay.setBounds(600, 64, 141, 61);
        contentPane.add(btnPlay);
        
        JButton btnInstructions = new JButton("INSTRUCTIONS");
        
        btnInstructions.setBounds(600, 160, 141, 61);
        btnInstructions.setBackground(Color.BLACK);
        btnInstructions.setFocusPainted(false);
       // btnInstructions.setEnabled(true);
        
        contentPane.add(btnInstructions);
        repaint();
        pack(); 
        setVisible(true);
        
    }
    
}

Upvotes: 2

Views: 5881

Answers (4)

MadProgrammer
MadProgrammer

Reputation: 347194

Swing uses a "layering" concept for it's painting...

paint calls paintComponent, paintBorder and paintChildren. By overriding paint and failing to call super.paint, you've prevented the component from painting it's various layers.

In Swing, it is preferred to use paintComponent to provide custom painting, which allows you to paint underneath any other components that might be added to the component.

enter image description here

public class TestPaint01 {

  public static void main(String[] args) {
    new TestPaint01();
  }

  public TestPaint01() {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        try {
          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
        }

        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TestPane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

      }
    });
  }

  public class TestPane extends JPanel {

    private Image backgroundImage;

    public TestPane() {
      try {
        BufferedImage background = ImageIO.read(new File("/path/to/image.jpg"));
        //backgroundImage = background.getScaledInstance(-1, background.getHeight() / 4, Image.SCALE_SMOOTH);
        backgroundImage = background;
      } catch (IOException ex) {
        ex.printStackTrace();
      }
      setLayout(new GridBagLayout());
      add(new JButton("Hello"));
    }

    @Override
    public Dimension getPreferredSize() {
      return backgroundImage == null ? super.getPreferredSize() : new Dimension(backgroundImage.getWidth(this), backgroundImage.getHeight(this));
    }

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      int x = (getWidth() - backgroundImage.getWidth(this)) / 2;
      int y = (getHeight() - backgroundImage.getHeight(this)) / 2;
      g.drawImage(backgroundImage, x, y, this);
    }

  }

}

You might find A Closer look at the Paint Mechanism and Painting in AWT and Swing informative.

Upvotes: 3

Roman C
Roman C

Reputation: 1

Since you are using Swing and JFrame the painting mechanism used to override paintComponent not paint that is usually used with applets or AWT.

Upvotes: 2

JB Nizet
JB Nizet

Reputation: 691715

You're overriding paint() but don't call super.paint(). So the normal painting of the components done by the JFrame's paint() method implementation is not executed.

Upvotes: 2

Adude11
Adude11

Reputation: 605

I think it's because you're overriding the paint method. It's better to override repaint, then call super.repaint(); Like this:

public void repaint(Graphics g)
        {
             super.repaint(g);
         // Draws the img to the BackgroundPanel.
             System.out.println("paint");
           g.drawImage(bg, 0, 0, null);
        }

Then the components get redrawn as well.

But if all you want to do is show an image as the background see here.

Upvotes: 2

Related Questions