Moving JPasswordField to absolute position

最后都变了- 提交于 2019-11-28 02:29:18
MadProgrammer

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

Updated with layout manager example

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

}

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...

You could use a null layout, but that takes too long and it doesn't re-size with the frame. Like this:

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

}

And that should work. If you want to use a null layout.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!