将 JPasswordField 移动到绝对位置
Moving JPasswordField to absolute position
我有这个代码:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class DialogExample extends JPanel {
private static final int COLUMN_COUNT = 10;
private static final int I_GAP = 3;
public static final String BKG_IMG_PATH = "http://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/9/92/Camels_in_Jordan_valley_%284568207363%29.jpg/800px-Camels_in_Jordan_valley_"
+ "%284568207363%29.jpg";
private BufferedImage backgrndImage;
private JTextField userNameField = new JTextField();
private JPasswordField passwordField = new JPasswordField();
private JPanel mainPanel = new JPanel(new GridBagLayout());
private JButton okButton = new JButton("OK");
private JButton cancelButton = new JButton("Cancel");
public DialogExample(BufferedImage backgrndImage) {
this.backgrndImage = backgrndImage;
userNameField.setColumns(COLUMN_COUNT);
passwordField.setColumns(COLUMN_COUNT);
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
btnPanel.setOpaque(false);
btnPanel.add(okButton);
btnPanel.add(cancelButton);
GridBagConstraints gbc = getGbc(0, 0, GridBagConstraints.BOTH);
mainPanel.add(createLabel("User Name", Color.white), gbc);
gbc = getGbc(1, 0, GridBagConstraints.HORIZONTAL);
mainPanel.add(userNameField, gbc);
gbc = getGbc(0, 1, GridBagConstraints.BOTH);
mainPanel.add(createLabel("Password:", Color.white), gbc);
gbc = getGbc(1, 1, GridBagConstraints.HORIZONTAL);
mainPanel.add(passwordField, gbc);
gbc = getGbc(0, 2, GridBagConstraints.BOTH, 2, 1);
mainPanel.add(btnPanel, gbc);
mainPanel.setOpaque(false);
add(mainPanel);
}
private JLabel createLabel(String text, Color color) {
JLabel label = new JLabel(text);
label.setForeground(color);
return label;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgrndImage != null) {
g.drawImage(backgrndImage, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || backgrndImage == null) {
return super.getPreferredSize();
}
int imgW = backgrndImage.getWidth();
int imgH = backgrndImage.getHeight();
return new Dimension(imgW, imgH);
}
public static GridBagConstraints getGbc(int x, int y, int fill) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
gbc.fill = fill;
return gbc;
}
public static GridBagConstraints getGbc(int x, int y, int fill, int width,
int height) {
GridBagConstraints gbc = getGbc(x, y, fill);
gbc.gridwidth = width;
gbc.gridheight = height;
return gbc;
}
private static void createAndShowGui() throws IOException {
final JFrame frame = new JFrame("Frame");
final JDialog dialog = new JDialog(frame, "User Sign-In", ModalityType.APPLICATION_MODAL);
URL imgUrl = new URL(BKG_IMG_PATH);
BufferedImage img = ImageIO.read(imgUrl);
final DialogExample dlgExample = new DialogExample(img);
dialog.add(dlgExample);
dialog.pack();
JPanel mainPanel = new JPanel();
mainPanel.add(new JButton(new AbstractAction("Please Press Me!") {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
}));
mainPanel.setPreferredSize(new Dimension(800, 650));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
如何将 JPasswordField 移动到绝对位置 (X,Y)?我一直在尝试不同的东西,比如 setPosition(int X, int Y) 但没有任何效果。我也尝试过布局,但也没有成功。我只想在他的右边有一个 JPasswordField 对象和一个按钮对象。就是这样
谢谢
首先为密码字段和按钮创建一个面板。接下来,随机化 EmptyBorder
和 GridBagConstraints
的 Insets
以定义父容器内的不同位置。使用这些随机约束将 password/button 面板添加到此容器...
public class TestPane extends JPanel {
public TestPane() {
Random rnd = new Random();
JPanel panel = new JPanel();
JPasswordField pf = new JPasswordField(10);
JButton btn = new JButton("Login");
panel.add(pf);
panel.add(btn);
panel.setBorder(new EmptyBorder(rnd.nextInt(10), rnd.nextInt(10), rnd.nextInt(10), rnd.nextInt(10)));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(rnd.nextInt(100), rnd.nextInt(100), rnd.nextInt(100), rnd.nextInt(100));
add(panel, gbc);
}
}
另一种选择是编写您自己的自定义布局管理器...但如果可以避免,上面的示例要简单得多...
ps- 您可以随机化边框或插图,也许使用更大的随机范围并获得相同的效果,我更简单地使用两者来证明这一点;)
更新了布局管理器示例
public class TestPane extends BackgroundImagePane {
public TestPane() throws IOException {
super(ImageIO.read(new File("Path/to/your/image")));
Random rnd = new Random();
JPanel panel = new JPanel();
panel.setOpaque(false);
JPasswordField pf = new JPasswordField(10);
JButton btn = new JButton("Login");
panel.add(pf);
panel.add(btn);
setLayout(new RandomLayoutManager());
Dimension size = getPreferredSize();
size.width -= panel.getPreferredSize().width;
size.height -= panel.getPreferredSize().height;
add(panel, new Point(rnd.nextInt(size.width), rnd.nextInt(size.height)));
}
}
public class RandomLayoutManager implements LayoutManager2 {
private Map<Component, Point> mapConstraints;
public RandomLayoutManager() {
mapConstraints = new WeakHashMap<>(25);
}
@Override
public void addLayoutComponent(String name, Component comp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void removeLayoutComponent(Component comp) {
mapConstraints.remove(comp);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
Area area = new Area();
for (Component comp : mapConstraints.keySet()) {
Point p = mapConstraints.get(comp);
Rectangle bounds = new Rectangle(p, comp.getPreferredSize());
area.add(new Area(bounds));
}
Rectangle bounds = area.getBounds();
Dimension size = bounds.getSize();
size.width += bounds.x;
size.height += bounds.y;
return size;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
for (Component comp : mapConstraints.keySet()) {
Point p = mapConstraints.get(comp);
comp.setLocation(p);
comp.setSize(comp.getPreferredSize());
}
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof Point) {
mapConstraints.put(comp, (Point) constraints);
} else {
throw new IllegalArgumentException("cannot add to layout: constraint must be a java.awt.Point");
}
}
@Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void invalidateLayout(Container target) {
}
}
public class BackgroundImagePane extends JPanel {
private Image image;
public BackgroundImagePane(Image img) {
this.image = img;
}
@Override
public Dimension getPreferredSize() {
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
}
BackgroundImagePane
基于 this example,允许背景图像面板成为现场面板的容器,您应该一切顺利...
您可以使用 null
布局,但这会花费太长时间,而且它不会随框架调整大小。
像这样:
public class TestPane{
public static void main (String[] args) {
Random rnd = new Random();
JFrame frame = new JFrame();
JPasswordField pf = new JPasswordField();
JButton btn = new JButton("Login");
frame.setSize(500, 500);
frame.setLayout(null);
btn.setBounds(y, x, width, height);
pf.setBounds(y, x, width, height);
frame.add(btn);
frame.add(pf);
}
}
这应该行得通。
如果你想使用空布局。
我有这个代码:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class DialogExample extends JPanel {
private static final int COLUMN_COUNT = 10;
private static final int I_GAP = 3;
public static final String BKG_IMG_PATH = "http://upload.wikimedia.org/wikipedia/commons/"
+ "thumb/9/92/Camels_in_Jordan_valley_%284568207363%29.jpg/800px-Camels_in_Jordan_valley_"
+ "%284568207363%29.jpg";
private BufferedImage backgrndImage;
private JTextField userNameField = new JTextField();
private JPasswordField passwordField = new JPasswordField();
private JPanel mainPanel = new JPanel(new GridBagLayout());
private JButton okButton = new JButton("OK");
private JButton cancelButton = new JButton("Cancel");
public DialogExample(BufferedImage backgrndImage) {
this.backgrndImage = backgrndImage;
userNameField.setColumns(COLUMN_COUNT);
passwordField.setColumns(COLUMN_COUNT);
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
btnPanel.setOpaque(false);
btnPanel.add(okButton);
btnPanel.add(cancelButton);
GridBagConstraints gbc = getGbc(0, 0, GridBagConstraints.BOTH);
mainPanel.add(createLabel("User Name", Color.white), gbc);
gbc = getGbc(1, 0, GridBagConstraints.HORIZONTAL);
mainPanel.add(userNameField, gbc);
gbc = getGbc(0, 1, GridBagConstraints.BOTH);
mainPanel.add(createLabel("Password:", Color.white), gbc);
gbc = getGbc(1, 1, GridBagConstraints.HORIZONTAL);
mainPanel.add(passwordField, gbc);
gbc = getGbc(0, 2, GridBagConstraints.BOTH, 2, 1);
mainPanel.add(btnPanel, gbc);
mainPanel.setOpaque(false);
add(mainPanel);
}
private JLabel createLabel(String text, Color color) {
JLabel label = new JLabel(text);
label.setForeground(color);
return label;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (backgrndImage != null) {
g.drawImage(backgrndImage, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || backgrndImage == null) {
return super.getPreferredSize();
}
int imgW = backgrndImage.getWidth();
int imgH = backgrndImage.getHeight();
return new Dimension(imgW, imgH);
}
public static GridBagConstraints getGbc(int x, int y, int fill) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.insets = new Insets(I_GAP, I_GAP, I_GAP, I_GAP);
gbc.fill = fill;
return gbc;
}
public static GridBagConstraints getGbc(int x, int y, int fill, int width,
int height) {
GridBagConstraints gbc = getGbc(x, y, fill);
gbc.gridwidth = width;
gbc.gridheight = height;
return gbc;
}
private static void createAndShowGui() throws IOException {
final JFrame frame = new JFrame("Frame");
final JDialog dialog = new JDialog(frame, "User Sign-In", ModalityType.APPLICATION_MODAL);
URL imgUrl = new URL(BKG_IMG_PATH);
BufferedImage img = ImageIO.read(imgUrl);
final DialogExample dlgExample = new DialogExample(img);
dialog.add(dlgExample);
dialog.pack();
JPanel mainPanel = new JPanel();
mainPanel.add(new JButton(new AbstractAction("Please Press Me!") {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(true);
}
}));
mainPanel.setPreferredSize(new Dimension(800, 650));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
createAndShowGui();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
如何将 JPasswordField 移动到绝对位置 (X,Y)?我一直在尝试不同的东西,比如 setPosition(int X, int Y) 但没有任何效果。我也尝试过布局,但也没有成功。我只想在他的右边有一个 JPasswordField 对象和一个按钮对象。就是这样
谢谢
首先为密码字段和按钮创建一个面板。接下来,随机化 EmptyBorder
和 GridBagConstraints
的 Insets
以定义父容器内的不同位置。使用这些随机约束将 password/button 面板添加到此容器...
public class TestPane extends JPanel {
public TestPane() {
Random rnd = new Random();
JPanel panel = new JPanel();
JPasswordField pf = new JPasswordField(10);
JButton btn = new JButton("Login");
panel.add(pf);
panel.add(btn);
panel.setBorder(new EmptyBorder(rnd.nextInt(10), rnd.nextInt(10), rnd.nextInt(10), rnd.nextInt(10)));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(rnd.nextInt(100), rnd.nextInt(100), rnd.nextInt(100), rnd.nextInt(100));
add(panel, gbc);
}
}
另一种选择是编写您自己的自定义布局管理器...但如果可以避免,上面的示例要简单得多...
ps- 您可以随机化边框或插图,也许使用更大的随机范围并获得相同的效果,我更简单地使用两者来证明这一点;)
更新了布局管理器示例
public class TestPane extends BackgroundImagePane {
public TestPane() throws IOException {
super(ImageIO.read(new File("Path/to/your/image")));
Random rnd = new Random();
JPanel panel = new JPanel();
panel.setOpaque(false);
JPasswordField pf = new JPasswordField(10);
JButton btn = new JButton("Login");
panel.add(pf);
panel.add(btn);
setLayout(new RandomLayoutManager());
Dimension size = getPreferredSize();
size.width -= panel.getPreferredSize().width;
size.height -= panel.getPreferredSize().height;
add(panel, new Point(rnd.nextInt(size.width), rnd.nextInt(size.height)));
}
}
public class RandomLayoutManager implements LayoutManager2 {
private Map<Component, Point> mapConstraints;
public RandomLayoutManager() {
mapConstraints = new WeakHashMap<>(25);
}
@Override
public void addLayoutComponent(String name, Component comp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void removeLayoutComponent(Component comp) {
mapConstraints.remove(comp);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
Area area = new Area();
for (Component comp : mapConstraints.keySet()) {
Point p = mapConstraints.get(comp);
Rectangle bounds = new Rectangle(p, comp.getPreferredSize());
area.add(new Area(bounds));
}
Rectangle bounds = area.getBounds();
Dimension size = bounds.getSize();
size.width += bounds.x;
size.height += bounds.y;
return size;
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
for (Component comp : mapConstraints.keySet()) {
Point p = mapConstraints.get(comp);
comp.setLocation(p);
comp.setSize(comp.getPreferredSize());
}
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof Point) {
mapConstraints.put(comp, (Point) constraints);
} else {
throw new IllegalArgumentException("cannot add to layout: constraint must be a java.awt.Point");
}
}
@Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void invalidateLayout(Container target) {
}
}
public class BackgroundImagePane extends JPanel {
private Image image;
public BackgroundImagePane(Image img) {
this.image = img;
}
@Override
public Dimension getPreferredSize() {
return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
int x = (getWidth() - image.getWidth(this)) / 2;
int y = (getHeight() - image.getHeight(this)) / 2;
g.drawImage(image, x, y, this);
}
}
}
BackgroundImagePane
基于 this example,允许背景图像面板成为现场面板的容器,您应该一切顺利...
您可以使用 null
布局,但这会花费太长时间,而且它不会随框架调整大小。
像这样:
public class TestPane{
public static void main (String[] args) {
Random rnd = new Random();
JFrame frame = new JFrame();
JPasswordField pf = new JPasswordField();
JButton btn = new JButton("Login");
frame.setSize(500, 500);
frame.setLayout(null);
btn.setBounds(y, x, width, height);
pf.setBounds(y, x, width, height);
frame.add(btn);
frame.add(pf);
}
}
这应该行得通。 如果你想使用空布局。