JButton仅在鼠标悬停时出现?

3

这里是我的代码:我删除了一些我认为不必要的内容。可能我也删掉了一些括号,但我只是想展示我有的内容。

问题是,当我运行程序时,背景图像被绘制出来(它是资源中的PNG文件),只有一个按钮出现(我的PLAY按钮),这是第一个按钮 - 它是自动选择的。

实际上我有四个按钮,但我只在代码中包含了PLAY和INSTRUCTIONS。其他三个按钮除非我将鼠标悬停在它们上面否则不会显示出来。我知道这可能与paint方法有关,但我不知道该如何修复它。

如果我选择另一个按钮并最小化窗口,然后再打开它,那么选定的按钮就是唯一显示的按钮。我必须将鼠标悬停在上面才能让其他按钮显示出来。

我还在paint方法中添加了super.paint(),我得到了所有的按钮,但背景是灰色的。我认为问题是super.paint()会绘制出所有的按钮,而g.drawImage(bg, 0, 0, null)只会绘制出我的背景,我不能做到两者兼顾。

如果这段话有点乱,请原谅。我是Java的新手,我很难表达我的意思。

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

    }

}

请将您的代码粘贴在此处(不要在评论中,而是在问题中使用编辑链接) - JB Nizet
尝试在你的主框架上放置 validate(); 方法。我认为它会起作用的。 - Mr Try Catch
4个回答

3
Swing使用“分层”概念进行绘制...
在重写`paint`方法时,通过不调用`super.paint`方法,阻止了组件的各个层次的绘制。Swing更倾向于使用`paintComponent`来进行自定义绘制,这样可以将自定义绘制放置在其他任何可能添加到组件中的组件下方。
[image]
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);
    }

  }

}

您可能会发现深入了解绘图机制AWT和Swing中的绘画非常有价值。


2

我认为这是因为你重写了paint方法。更好的做法是重写repaint方法,然后调用super.repaint(); 就像这样:

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

然后组件也会重新绘制。

但是如果你只想将图像显示为背景,请查看这里


@JessicaW 你试过我在帖子底部添加的代码了吗? - Adude11
我有问题 - 它不起作用。这是没有背景时发生的情况,但按钮会显示出来。 - Jessica W
这将在先前绘制的内容上绘制图像。最好使用paintComponent - MadProgrammer

2
您正在重写 paint() 方法,但没有调用 super.paint()。因此,JFrame 的 paint() 方法实现所完成的组件的正常绘制未被执行。

2

因为您正在使用 Swing 和 JFrame,所以绘制机制使用的是重写 paintComponent,而不是通常用于 applet 或 AWT 的 paint


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接