问题
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
回答1:
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.
回答2:
I'd like to find the simple solution that's most likely right in front of my eyes!
Something like this?
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);
}
});
}
}
来源:https://stackoverflow.com/questions/10929931/how-to-absolutely-position-a-jpanel-over-another-jpanel-with-setlayoutnull-and