【问题标题】:JButtons are painted over by an imageJButtons 被图像覆盖
【发布时间】:2015-04-02 03:07:14
【问题描述】:

我正在尝试为棋盘游戏风险制作一个主菜单。有一个自定义背景图像,理想情况下我希望按钮出现在图像上。但是,当我运行我的代码时,只会出现名为“New Game”的按钮,如果将鼠标悬停在其他按钮上,则会出现其他按钮。我几乎尝试了所有方法(这里有类似的问题),但似乎无法解决问题。也许它与我的代码有关?感谢任何帮助/建议!

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();


    }
}

【问题讨论】:

    标签: java swing jbutton


    【解决方案1】:

    绘制组件并不总是通知父组件或子组件。不要覆盖paint,而是尝试覆盖paintComponent 并在那里绘制背景,这就是paintComponent 的真正含义,绘制背景。

    您应该避免覆盖顶级容器的paint
    大多数顶级容器都有一系列层,包括JRootPanecontentPane 甚至是glassPane,所有这些都将绘制在框架的顶部。

    相反,创建一个自定义组件,它从 JPanel 之类的东西扩展而来,并将其用作您的基础组件。您可以覆盖它的 paintComponent 并在其中绘制背景。然后将此组件添加到您的框架中,甚至可以使其成为内容窗格。

    记住,如果一个组件是不透明的,它将覆盖所有子组件

    您还应该避免从任何绘制方法中加载资源(尤其是不断地重新加载它们),因为这会对您的程序的性能产生影响。绘画应该尽可能快。

    对于exampleexample

    【讨论】:

    • 不过,OP 使用 JFrame
    • 如果我尝试使用paintComponent,它会给我错误“Menu 类型的方法paintComponent(Graphics) 必须覆盖或实现超类型方法”所以如果我执行super.paintComponent(g),它会给我错误“JFrame 类型的方法paintComponent(Graphics) 未定义”因为我使用了@johnchen902 所述的JFrame。
    • @user2938241 然后不要,检查更新。覆盖顶级容器的paint 只会导致无穷无尽的问题和麻烦,最好避免
    • @MadProgrammer 哈哈我知道了。
    • @user2938241 这将是我的首选方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 2016-12-21
    • 1970-01-01
    • 2021-01-19
    相关资源
    最近更新 更多