Search code examples
javaswingjbutton

JButtons are painted over by an image


I'm trying to make a main menu for the board game risk. There's a custom background image, and ideally I would like the buttons to appear over the image. However when I run my code, only the button called "New Game" appears, and the other buttons will appear if you hover the mouse over them. I have tried just about everything (there are similar problems on here) but can't seem to fix the problem. Maybe it has something to do with my code? I appreciate any help/suggestions!

package View;


import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.SpringLayout;

/**
* These classes set up the GUI of the Risk program.
* The main menu, dialog for setting player count, dialog for name/color       settings for each 
 * player, the Risk game board, and a menu used during a Risk game session are    included.

 **/
public class Menu extends JFrame {  

    private JPanel mainPanel;


    private JButton newGameButton;
    private JButton loadGameButton;
    private JButton quitButton;
    private JButton ruleButton;

    private String newGameButtonName = "newGameBtn";
    private String loadGameButtonName = "loadGameBtn";
    private String quitButtonName = "quitBtn";
    private String ruleButtonName = "rulebtn";

    //private SpringLayout mainLayout;
     private static BufferedImage img;

    /**
     * Constructs the main menu.
     **/
    public Menu() 
    {
        add( mainMenu( ) );
        //setTitle("Risk: UConn Edition");
        setPreferredSize(new Dimension(640, 700));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setResizable(false);



        toFront();
        pack();

        setVisible(true);


    }

    /**
     * creates the buttons for the jPanel
     * 
     * @return
     */
    private JPanel mainMenu()
    {
        // Creates the panel
        mainPanel = new JPanel();
        // Sets Layout
        //mainLayout = new SpringLayout();
       mainPanel.setLayout(null);

        // Creates buttons
        newGameButton = new JButton("New Game");
        newGameButton.setBounds(20,300,150,50);
        newGameButton.setOpaque(false);
        newGameButton.setContentAreaFilled(false);
        newGameButton.setForeground(Color.RED);
        newGameButton.setBackground(Color.BLUE);

        loadGameButton = new JButton("Load Game");
        loadGameButton.setBounds(20,400,150,50);
        //loadGameButton.setOpaque(false);
        //loadGameButton.setContentAreaFilled(false);
        loadGameButton.setForeground(Color.RED);

        quitButton = new JButton("Quit");
        quitButton.setBounds(490,400,150,50);
        quitButton.setOpaque(false);
        quitButton.setContentAreaFilled(false);
        quitButton.setForeground(Color.RED);

        ruleButton = new JButton("Rules");
        ruleButton.setBounds(490,300,150,50);
        ruleButton.setOpaque(false);
        ruleButton.setContentAreaFilled(false);
        ruleButton.setForeground(Color.RED);

        // Sets button commands
        newGameButton.setActionCommand(newGameButtonName);
        loadGameButton.setActionCommand(loadGameButtonName);
        quitButton.setActionCommand(quitButtonName);

        // Adds buttons to mainPanel
        mainPanel.add(newGameButton);
        mainPanel.add(loadGameButton);
        mainPanel.add(quitButton);
        mainPanel.add(ruleButton);
    //  add(mainPanel);

        return mainPanel;
    }
    private Image createImage(){
        try {
            img = ImageIO.read(
                    Menu.class.getResource("../resource/riskUconn.jpg"));


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return img;
      }
    /**
     * paint method
     */
    @Override
    public void paint (Graphics g)  {

        Image img = createImage();
        g.drawImage(img, 20,20,this);
        super.paint(g);


      }


    // Action listeners for Menu
    protected void riskViewActionListeners(ActionListener evt)
    {
        newGameButton.addActionListener(evt);
        loadGameButton.addActionListener(evt);
        quitButton.addActionListener(evt);
    }



    public static void main(String [] args){
        Menu m = new Menu();


    }
}

Solution

  • Painting components doesn't always notify the parent or child components. Instead of overriding paint, try overriding paintComponent and paint your background there, this is what paintComponent is really meant for, painting the background.

    You should avoid overriding paint of top level containers.
    Most top level containers have a series of layers, including the JRootPane, contentPane and even a glassPane, all of which will paint over the top of the a frame.

    Instead, create a custom component, which extends from something like JPanel and use it as you base component. You can override it's paintComponent and paint the background within it. Then add this component to your frame, maybe even making it the content pane.

    Remember, if a component is opaque, it will cover any child components

    You should also avoid loading resources from within any paint method (especially continuously reloading them) as this can have a serve affect on the performance of your program. Painting should paint as fast as it can.

    For example and example