简体   繁体   中英

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

    }

}

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.

在此输入图像描述

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.

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.

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.

由于您使用的是Swing和JFrame因此用于覆盖paintComponent的绘制机制不会paint通常与applet或AWT一起使用的paint

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM