How to absolutely position a JPanel over another J

2019-05-19 05:00发布

I'm working with JFrames in Java, specifically with absolutely positioned elements that need to overlap. I understand that to overlay components, one should make a JPanel (with setOpacity(false);), and position it with either setBounds(x,y,x2,y2); or setPosition(x,y) & setSize(x,y). Unfortunately the panels act like CSS's inline-divs; they take up only the needed amount of room on their line, and do not stack.

This is the code I have so far, but it doesn't seem to act like I'd imagine it would:

class Login extends JFrame {
    private JPanel         backgroundpanel;
    private JPanel         panel;
    private JPanel         panel2;
    private JTextField     usernameBox;
    private JPasswordField passwordBox;
    private JButton        button;
    private int            height = 319;
    private int            width  = 452;
    private ImageIcon      ii     = new ImageIcon("special-window-BG.png");
    private JLabel         image;

    public Login() {
        setLayout(null);
        setTitle("Login");
        setSize(width,height);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(null);

        buildPanel();

        add(backgroundpanel);
        setVisible(true);
    }

    private void buildPanel() {
        usernameBox = new JTextField(20);
        passwordBox = new JPasswordField(20);
        button = new JButton("Login");
        image = new JLabel(ii);

        backgroundpanel = new JPanel();
        panel = new JPanel();
        panel2 = new JPanel();

        backgroundpanel.add(panel);
        backgroundpanel.add(panel2);
        backgroundpanel.add(image);

        panel.setBackground(Color.red);
        panel.setBounds(0, 0, 10, 10);
        panel.setOpaque(false);

        panel2.setBackground(Color.blue);
        panel2.setBounds(0, 0, 10, 10);
        panel2.setOpaque(false);

        panel.add(passwordBox);
        panel2.add(button);

        backgroundpanel.setOpaque(false);
        backgroundpanel.isOptimizedDrawingEnabled();
        backgroundpanel.setBounds(0, 0, width, height);

...cot'd, however unnecessary.

So basically, I'd like to know how to absolutely position JPanels (or JComponents, if that's simpler) over a JPanel with a background-image.

Thanks for taking a look at this question, I've spent far too much time on this method; the commented-out code extends nearly 500 lines passed what I posted, so I have nowhere else to turn to. The image below shows a crude illustration of what I'm trying to accomplish, I'm not sure if I'actually come close to getting it yet, because sometimes the JComponents seem to disappear as if they're behind the background image, however I'd like to find the simple solution that's most likely right in front of my eyes!

http://i.stack.imgur.com/revz8.jpg

2条回答
混吃等死
2楼-- · 2019-05-19 05:37

You're setting setLayout(null) on your JFrame but not on the "backgroundpanel" (which layout is default set to FlowLayout).

You shouldn't set layout of your Login frame - because it is default set to BorderLayout - and it's ok (you want the "backgroundpanel" to grow to match the parent). Instead setLayout(null) on your JPanel - "backgroundpanel" - to which you add your arbitrary positioned panels.

查看更多
祖国的老花朵
3楼-- · 2019-05-19 05:41

I'd like to find the simple solution that's most likely right in front of my eyes!

Something like this?

LoginPanel

import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class LoginPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    BufferedImage image;

    LoginPanel(BufferedImage image) {
        super(new GridBagLayout());

        this.image = image;

        JPanel controls = new JPanel(new BorderLayout(15,35));
        controls.setOpaque(false);
        controls.setBorder(new EmptyBorder(110,0,0,0));

        JPanel fields = new JPanel(new GridLayout(0,1,30,30));
        fields.setOpaque(false);
        controls.add(fields, BorderLayout.CENTER);
        fields.add(new JTextField(20));
        fields.add(new JPasswordField(20));

        JPanel button = new JPanel(new GridBagLayout());
        button.setOpaque(false);
        controls.add(button, BorderLayout.PAGE_END);
        button.add(new JButton("Log In"));

        Dimension prefSize = new Dimension(image.getWidth(),image.getHeight());
        setPreferredSize(prefSize);

        add(controls);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
    }

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://i.stack.imgur.com/revz8.jpg");
        final BufferedImage image = ImageIO.read(url); 
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                LoginPanel p = new LoginPanel(image);
                JOptionPane.showMessageDialog(null, p);
            }
        });
    }
}
查看更多
登录 后发表回答