Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XY Layout JAVA

Tags:

java

layout

is there any sort of XY-Layout to Java?

So I can set a Button at the X and Y cordinate and that it is suppose to be that big etc.... Because this border layout and grid and panel thing is driven me crazy. :)

They are flowing every were and getting strecht up. And to make them small you have to put panel in panel in panel in panel ^^,

like image 882
suxSx Avatar asked Jul 05 '26 06:07

suxSx


2 Answers

When setting the container's layout to null (no LayoutManager), you can set the component's bounds individually with component.setBounds(x,y,w,h).

Fixed layouts are in 99% of all cases bad UI design (if your labels, for example, don't get their preferred size you run into mayor problems when your application supports multiple languages), so my advice for you is to rather write a specialized layout manager for your specific needs.

Writing your custom layout manager is quite easy, all you have to do is to be able to calculate the preferred size for a container with given components and your layout, and to do the layout by setting the (calculated) bounds of your components. I got rid of the GridBagLayout and started coding my own layouts long ago, and layouting has never been easier.

Here's an example of a custom layout, that layouts pairs of key and value components:

public class KeyValueLayout implements LayoutManager {

    public static enum KeyAlignment {
        LEFT, RIGHT;
    }

    private KeyAlignment keyAlignment = KeyAlignment.LEFT;

    private int hgap;

    private int vgap;

    public KeyValueLayout () {
        this(KeyAlignment.LEFT);
    }

    public KeyValueLayout (KeyAlignment keyAlignment) {
        this(keyAlignment, 5, 5);
    }

    public KeyValueLayout (int hgap, int vgap) {
        this(KeyAlignment.LEFT, hgap, vgap);
    }

    public KeyValueLayout (KeyAlignment keyAlignment, int hgap, int vgap) {

        this.keyAlignment = keyAlignment != null ? keyAlignment : KeyAlignment.LEFT;
        this.hgap = hgap;
        this.vgap = vgap;
    }

    public void addLayoutComponent (String name, Component comp) {
    }

    public void addLayoutComponent (Component comp, Object constraints) {
    }

    public void removeLayoutComponent (Component comp) {
    }

    public void layoutContainer (Container parent) {
        Rectangle canvas = getLayoutCanvas(parent);
        int ypos = canvas.y;
        int preferredKeyWidth = getPreferredKeyWidth(parent);

        for (Iterator<Component> iter = new ComponentIterator(parent); iter.hasNext();) {
            Component key = (Component) iter.next();
            Component value = iter.hasNext() ? (Component) iter.next() : null;
            int xpos = canvas.x;
            int preferredHeight = Math.max(key.getPreferredSize().height, value != null ? value.getPreferredSize().height : 0);

            if (keyAlignment == KeyAlignment.LEFT)
                key.setBounds(xpos, ypos, key.getPreferredSize().width, key.getPreferredSize().height);
            else
                key.setBounds(xpos + preferredKeyWidth - key.getPreferredSize().width, ypos, key.getPreferredSize().width,
                    key.getPreferredSize().height);

            xpos += preferredKeyWidth + hgap;
            if (value != null)
                value.setBounds(xpos, ypos, canvas.x + canvas.width - xpos, preferredHeight);
            ypos += preferredHeight + vgap;
        }
    }

    public Dimension minimumLayoutSize (Container parent) {
        int preferredKeyWidth = getPreferredKeyWidth(parent);
        int minimumValueWidth = 0;
        int minimumHeight = 0;
        int lines = 0;
        for (Iterator<Component> iter = new ComponentIterator(parent); iter.hasNext();) {
            lines++;
            Component key = (Component) iter.next();
            Component value = iter.hasNext() ? (Component) iter.next() : null;
            minimumHeight += Math.max(key.getPreferredSize().height, value != null ? value.getMinimumSize().height : 0);
            minimumValueWidth = Math.max(minimumValueWidth, value != null ? value.getMinimumSize().width : 0);
        }

        Insets insets = parent.getInsets();
        int minimumWidth = insets.left + preferredKeyWidth + hgap + minimumValueWidth + insets.right;
        minimumHeight += insets.top + insets.bottom;
        if (lines > 0)
            minimumHeight += (lines - 1) * vgap;

        return new Dimension(minimumWidth, minimumHeight);
    }

    public Dimension preferredLayoutSize (Container parent) {
        int preferredKeyWidth = getPreferredKeyWidth(parent);
        int preferredValueWidth = 0;
        int preferredHeight = 0;
        int lines = 0;
        for (Iterator<Component> iter = new ComponentIterator(parent); iter.hasNext();) {
            lines++;
            Component key = (Component) iter.next();
            Component value = iter.hasNext() ? (Component) iter.next() : null;

            preferredHeight += Math.max(key.getPreferredSize().height, value != null ? value.getPreferredSize().height : 0);
            preferredValueWidth = Math.max(preferredValueWidth, value != null ? value.getPreferredSize().width : 0);
        }

        Insets insets = parent.getInsets();
        int preferredWidth = insets.left + preferredKeyWidth + hgap + preferredValueWidth + insets.right;
        preferredHeight += insets.top + insets.bottom;
        if (lines > 0)
            preferredHeight += (lines - 1) * vgap;

        return new Dimension(preferredWidth, preferredHeight);
    }

    public Dimension maximumLayoutSize (Container target) {
        return preferredLayoutSize(target);
    }

    private int getPreferredKeyWidth (Container parent) {
        int preferredWidth = 0;
        for (Iterator<Component> iter = new ComponentIterator(parent); iter.hasNext();) {
            Component key = (Component) iter.next();
            if (iter.hasNext())
                iter.next();

            preferredWidth = Math.max(preferredWidth, key.getPreferredSize().width);
        }

        return preferredWidth;
    }

    private Rectangle getLayoutCanvas (Container parent) {
        Insets insets = parent.getInsets();
        int x = insets.left;
        int y = insets.top;

        int width = parent.getSize().width - insets.left - insets.right;
        int height = parent.getSize().height - insets.top - insets.bottom;

        return new Rectangle(x, y, width, height);
    }

    private class ComponentIterator implements Iterator<Component> {

        private Container container;

        private int index = 0;

        public ComponentIterator (Container container) {
            this.container = container;
        }

        public boolean hasNext () {
            return index < container.getComponentCount();
        }

        public Component next () {
            return container.getComponent(index++);
        }

        public void remove () {
        }
    }
}

Just set the layout and add alternatingly labels and value components. It's easy to use, especially compared to GridBagLayout or nested panels with custom layouts.

like image 85
Peter Walser Avatar answered Jul 07 '26 19:07

Peter Walser


The reason components resize is so stuff looks nice whatever size the window is, so Swing discourages straight X-Y position. You might want to have a look at GroupLayout http://java.sun.com/docs/books/tutorial/uiswing/layout/group.html which is designed for GUI builders, and the page mentioned above describes using invisible components to absorb the stretches. eg:layout.setAutoCreateGaps(true);

SpringLayout might also be useful - see the visual guide

If you really want X and Y then set the layout manager to null, and use setLocation() or setBounds(). I REALLY REALLY wouldn't recommend this, but it does work. Have a read of this tutorial

like image 30
Nick Fortescue Avatar answered Jul 07 '26 18:07

Nick Fortescue



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!