问题
I want to have multiple textfiled to be aligned in a customized order, so that they are on the top of the background image. I tried to use setBounds
but it did not work:
import javax.swing.*;
public class TestJP {
public static void main(String[] args) {
JLabel myLabel = new JLabel();
myLabel.setIcon ( new ImageIcon("system\\myBackground.jpg"));
myLabel.setBounds(0,0,750,500);
JTextField login = new JTextField(5);
login.setBounds(50,50,20,100); // This does not work
JPasswordField password = new JPasswordField(5);
password.setBounds( 50, 70, 20, 100); // Doesn't help either
JPanel myPanel = new JPanel();
myPanel.add(myLabel);
myPanel.add(login);
myPanel.add(password);
int result = JOptionPane.showConfirmDialog(null, myPanel,
"Please Login", JOptionPane.OK_CANCEL_OPTION);
// etc
}
}
回答1:
Don't use setBounds()
. Swing was designed to be used with layout managers.
You can add the text fields to the label by doing something like:
JLabel myLabel = new JLabel( new ImageIcon("system\\myBackground.jpg") );
mylabel.setLayout( new FlowLayout() );
mylabel.add(login);
mylabel.add(password);
Use the appropriate layout manager for the label to get the desired layout.
回答2:
"I tried to use setBounds but it did not work:"
- Use the layout managers as that's what they're for. You can find the layout manager tutorial here.
- Add a layout to the JLabel that is displaying the image.
- Add your JTextFields to that JLabel.
- Display the JLabel in your JOptionPane.
For more help, post an image of what you're trying to do.
Edit You state in a comment:
Thank You! I used setBounds many times in a contentPane ... It worked fine.
While as a newbie, you will find that setBounds and null layouts seem easier to work with, the longer you code with swing, the more involved your GUI's the more you'll find that null layouts will fail youy, will look terrible on different platform, will be inflexible and not allow you to update or improve your GUI later.
How come it doesn't work for JOptionPane? The regular Layout managers are not precise ... I do not want to use those: east, west
It has nothing to do with JOptionPane and all to do with how you're not creating your GUI correctly. Learn to use the layout managers and they will be easier to use.
Edit 2 For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.*;
public class GridBagEg {
public static final String IMG_PATH = "https://duke.kenai.com/tshirts/.Midsize/Tshirt1997.png.png";
private static void createAndShowGui() {
BufferedImage img = null;
try {
URL imgUrl = new URL(IMG_PATH);
img = ImageIO.read(imgUrl);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
PlayerEditorPanel playerEditorPane = new PlayerEditorPanel(img);
int result = JOptionPane.showConfirmDialog(null, playerEditorPane,
"Edit Player", JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
// TODO: do something with info
for (PlayerEditorPanel.FieldTitle fieldTitle :
PlayerEditorPanel.FieldTitle.values()) {
System.out.printf("%10s: %s%n", fieldTitle.getTitle(),
playerEditorPane.getFieldText(fieldTitle));
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class PlayerEditorPanel extends JPanel {
enum FieldTitle {
NAME("Name"), SPEED("Speed"), STRENGTH("Strength");
private String title;
private FieldTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
};
private static final Insets WEST_INSETS = new Insets(5, 0, 5, 5);
private static final Insets EAST_INSETS = new Insets(5, 5, 5, 0);
private static final double SCALE = 0.4;
private Map<FieldTitle, JTextField> fieldMap = new HashMap<FieldTitle, JTextField>();
private BufferedImage backgroundImg = null;
private int imgWidth;
private int imgHeight;
public PlayerEditorPanel(BufferedImage img) {
this.backgroundImg = img;
imgWidth = (int) (backgroundImg.getWidth() * SCALE);
imgHeight = (int) (backgroundImg.getHeight() * SCALE);
setLayout(new GridBagLayout());
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createTitledBorder("Player Editor"),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
GridBagConstraints gbc;
for (int i = 0; i < FieldTitle.values().length; i++) {
FieldTitle fieldTitle = FieldTitle.values()[i];
gbc = createGbc(0, i);
JLabel fieldLabel = new JLabel(fieldTitle.getTitle() + ":",
JLabel.LEFT);
fieldLabel.setForeground(new Color(200, 10, 10));
fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD, 24f));
add(fieldLabel, gbc);
gbc = createGbc(1, i);
JTextField textField = new JTextField(10);
add(textField, gbc);
fieldMap.put(fieldTitle, textField);
}
}
@Override
@Transient
public Dimension getPreferredSize() {
if (backgroundImg != null) {
return new Dimension(imgWidth, imgHeight);
}
return super.getPreferredSize();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgroundImg != null) {
g.drawImage(backgroundImg, 0, 0, imgWidth, imgHeight, this);
}
}
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.anchor = (x == 0) ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.fill = (x == 0) ? GridBagConstraints.BOTH
: GridBagConstraints.HORIZONTAL;
gbc.insets = (x == 0) ? WEST_INSETS : EAST_INSETS;
gbc.weightx = (x == 0) ? 0.1 : 1.0;
gbc.weighty = 1.0;
return gbc;
}
public String getFieldText(FieldTitle fieldTitle) {
return fieldMap.get(fieldTitle).getText();
}
}
Which displays a JOptionPane like so:
来源:https://stackoverflow.com/questions/17872099/how-to-align-multiple-textfields-on-a-background-image-within-a-joptionpane