ruyili
ruyili

Reputation: 703

java - Put JComponent in front of graphics in NullLayoutManager?

I have a JButton in a JPanel that has graphics, but the button won't show as it is in the layer BELOW the graphics. I've already read this : Put JLabel in front of Graphics 2D Rectangle in JPanel

But the answers tell me not to use the NullLayoutManager. Is there any way to do it with the NullLayoutManager, because I need to specifically position my JButton in my JPanel? If this is not possible, are there any other ways I can position a JComponent at a position x, y? I've also googled that and NullLayoutManager is what the world wide web gives me.

Code:

    JPanel p = new JPanel(){

        @Override
        public void paintComponent(Graphics gr){
            Graphics2D g = (Graphics2D) gr;
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, 800, 800);
            g.setFont(titlefont);
            g.setColor(Color.WHITE);
            g.drawString("dont steal my game idea plz", 25, 100);
            g.drawImage(bi, 138, 70, null);
            repaint();
        }

    };
    p.setLayout(null);





    JButton b = new JButton("PLAY");
    b.setLocation(100, 200);
    b.setFont(ufont);




    f.add(p);
    p.add(b);

Upvotes: 0

Views: 733

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347244

Is there any way to do it with the NullLayoutManager, because I need to specifically position my JButton in my JPanel?

The answer is "yes", but do you understand what the layout managers actually do? How they work and the role they fill in order to replace them and take over the requirements of their functionality?

null layouts are just a bad idea, there are so many things that can wrong with them it's mind numbing just trying to think about it. If none of the stock layout managers do what you want, maybe consider using MigLayout or some other layout manager, possibly even writing your own, at least this way, you will still be able to work within the API, which has been designed to work around layout managers.

There are a couple of other issues, first, you're painting your image AFTER the paint the text, this could cause some issues if the two overlap. Second, you're breaking the paint chain by not calling super.paintComponent, this could result in some unexpected and unwanted results. Third, you don't need to fill the component, use setBackground and let the super.paintComponent deal with it.

Play this

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class DownWithNullLayouts {

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

    public DownWithNullLayouts() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

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

    public class TestPane extends JPanel {

        private Font titlefont;
        private BufferedImage bi;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(30, 0, 0, 0);
            add(new JButton("Play"), gbc);
            try {
                bi = ImageIO.read(...);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            titlefont = UIManager.getFont("Label.font");
            setBackground(Color.BLACK);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - bi.getWidth()) / 2;
            int y = (getHeight()- bi.getHeight()) / 2;
            g2d.drawImage(bi, x, y, this);
            g2d.setFont(titlefont);
            g2d.setColor(Color.WHITE);
            g2d.drawString("dont steal my game idea plz", 25, 100);
            g2d.dispose();
        }

    }

}

Take a closer look at Painting in AWT and Swing and Performing Custom Painting for more details

Upvotes: 1

Related Questions