将 JPasswordField 移动到绝对位置 [英] Moving JPasswordField to absolute position

查看:20
本文介绍了将 JPasswordField 移动到绝对位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

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 对象和一个按钮对象.就这样

Ho can I move the JPasswordField to a absolute position (X,Y)?? I've been trying different things like setPosition(int X, int Y) and nothing worked. I tryed playing too with the layout but not success either. I would like to have just a JPasswordField object and a button object on his right. that's it

谢谢

推荐答案

首先为密码字段和要驻留的按钮创建一个面板.接下来,随机化 EmptyBorderGridBagConstraintsInsets 以定义父容器内的不同位置.使用这些随机约束将密码/按钮面板添加到此容器中...

Start by creating a panel for the password field and button to reside on. Next, randomise a EmptyBorder and the Insets of a GridBagConstraints to define different locations within the parent container. Add the password/button panel to this container with these randomised constraints...

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);

    }

}

另一种选择是编写自己的自定义布局管理器...但如果可以避免的话,上面的例子就简单得多...

The other choice would be to write your own custom layout manager...but if you can avoid it, the above example is MUCH simpler...

ps- 您可以随机化边界或插图,也许使用更大的随机范围并获得相同的效果,我更简单地使用两者来证明这一点;)

ps- You could randomise either the border OR the insets, maybe using a larger random range and get the same effect, I've simpler used both to demonstrate the point ;)

更新了布局管理器示例

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 基于 这个例子,允许背景图像面板成为字段面板的容器,你应该很好...

The BackgroundImagePane is based on this example, allowing the background image panel to be the container for the field panel and you should be well on your way...

这篇关于将 JPasswordField 移动到绝对位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆