4

I'm really stuck with a layout I have to make with java swing.

I have to build a dynamic form, while iterating through a vector of labels and input components.

Here is how it should:

enter image description here

In this image, you can see, what should be the result. Between the green lines is one pair of label/input component. I also get a constraint, telling me, if I have to lay them out in one row 50/50 or in two rows or in one row 25/75 or 75/25. Also the whole form must be resizable with the 50/50, 25/75 and 75/25 ratio still correct.

I tried GridBagLayout which worked quite nice, but as you can see in the first row in the picture, the label can be very long. So I used a JTextarea but GridBagLayout cut it off. I also treid JGoodies FormLayout, but also had trouble with the Textarea for long labels.

The 25/75 and 75/25 ratio is not that important, but actually it is also part of what I have to do.

I think it is just really difficult to make a Textarea expand its parent component.

I also read/wrote these aricles:

but I'm still stuck.

Does any one of you has any idea on how to accomplish this?

Thanks

Community
  • 1
  • 1
haferblues
  • 2,155
  • 4
  • 26
  • 39
  • 2
    +1 but stick this image to your post and if you'll want to get reall answer then you have to identify which areas are/aren't resiziable, then for me your question make the sense – mKorbel Aug 15 '11 at 13:52
  • Also are the JTextArea with fixed text, or can the text change with user input? – toto2 Aug 15 '11 at 13:56
  • Not sure if this is useful to you, but maybe you could use JSplitPane for the rows that must be split in 25% / 75% parts. – S.L. Barth is on codidact.com Aug 15 '11 at 14:14

2 Answers2

1

It's been a while since I've done much Swing, but two thoughts:

  1. If a control is being cut off, that sounds like you're not setting the minimum size.

  2. I don't think any of the off-the-shelf layout managers have a feature to maintain a ratio of sizes like your 25/75 split. But don't despair! You can write your own layout manager. Back when I was doing a lot of Swinging I wrote several layout manager. (I would say, "for specialized requirements", but really they were for quite general requirements, and it always surprised me that Java didn't include canned layout managers to handle such things. Like: you often want a row or column of buttons where all the buttons are the same size, so you have to find what button has the longest text, and then resize all the others to match it. Or: set up rows and columns where each colum is sized to the widest thing in that column, but the width of one column has no effect on other columns; then similarly for rows.) Anyway, what you're describing IS fairly unusual, so you may just want to write your own layout manager.

The trick to writing a layout manager is just to implement a few key functions: (a) Calculate the X and Y co-ordinates where you'll place each control given the overall size; (b) Calculate the minimum size required; (c) Calculate the preferred size; (d) Calculate the maximum size you'll use. Umm, there may be one or two more I'm forgetting, but it's not that big a deal. When I first thought about "writing my own layout manager" that sounded to me like "write your own database engine" or "write your own compiler" at first, but it's not really anywhere near that scary. It's typically a few hundred lines of code.

Of course if someone else on here can tell you how to do what you want to do with one of the canned layout managers, that's surely a lot easier.

Jay
  • 26,876
  • 10
  • 61
  • 112
  • 1
    See also [Creating a Custom Layout Manager](http://download.oracle.com/javase/tutorial/uiswing/layout/custom.html). – trashgod Aug 15 '11 at 15:52
  • 1
    @trashgod: Thanks. If the OP pursues this, I'm sure he'll need more help than my 2 sentences. You might also want to look at the source code for existing layout managers -- that was how I figured out how to do it. (If you don't have the Java source code, download it from Oracle. It's often helpful. "Use the source, Duke.") – Jay Aug 15 '11 at 18:12
  • I finally wrote my own Layout Manager and it works nearly perfectly. I now only have a problem with the scrolling, but I will open a new thread for this in a few minites ;-) By the way: You are great! – haferblues Aug 16 '11 at 09:05
0

Here is what I got so far. This example only uses JTextArea, but it works with other components as well (like my picture shows). The only thing it can't do at the moment is layout the components like in row 3 in the picture above (one on top of the other), but this should be no problem.

Maybe this helps someone to find out, how to write a custom layout manager.

import java.awt.*;
import javax.swing.*;

public class SwingApp extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                final SwingApp app = new SwingApp();
            }
        });
    }

    private SwingApp() {
        setTitle(":)");
        setSize(800, 450);
        setResizable(true);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        /*JTextArea textArea = new JTextArea("111111alks jdfksajfjsaölk jfölksajfölkjsa 
        lkfj salkjflkdsjf ölsajfölksaj fölkjs flkjdsa flkjsaölkfjsölk");*/
        //textArea.setLineWrap(true);
        //this.getContentPane().add(textArea);
        this.getContentPane().setLayout(new MyListLayoutManager());
        add(20, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(50, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
        add(70, "left ajdskfj lksajdf dsafj lkdsjflksjalkfjsalk jlksjaf salkjfjdsflkjdslkfjlks "
                + "flk salkfjdslkfjlkds flkjds lkfjdslkfjlkds flkjds fljlfd left", "right dksjf "
                + "asjfjsa jfsjföldsajföljsa ölkfjdsaölk jf0932875 0983 09584093859438 095843 "
                + "5lkjf lksa jf lkdsajf 923879 825094lkjtwj lkdsf27509425 right");
    }

    private void add(final int leftPercent, final String leftText, final String rightText) {
        final JPanel panel = new JPanel(new MyRowLayoutManager(leftPercent));
        final JTextArea left = new JTextArea(leftText);
        left.setLineWrap(true);
        final JTextArea right = new JTextArea(rightText);
        right.setLineWrap(true);
        panel.add(left);
        panel.add(right);
        this.getContentPane().add(panel);
    }

    private class MyListLayoutManager implements LayoutManager {

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            final Dimension size = parent.getSize();
            final int left = 0;
            int top = 0;
            for (int i = 0; i < parent.getComponentCount(); ++i) {
                final Component component = parent.getComponent(i);
                component.setSize(size.width, 1);
                final Dimension preferredSize = component.getPreferredSize();
                component.setBounds(left, top, preferredSize.width, preferredSize.height);
                top += preferredSize.height;
            }
        }
    }

    private class MyRowLayoutManager implements LayoutManager {

        private final int _leftPercent;

        private MyRowLayoutManager(final int leftPercent) {
            _leftPercent = leftPercent;
        }

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

        @Override
        public void removeLayoutComponent(final Component comp) {
        }

        @Override
        public Dimension preferredLayoutSize(final Container parent) {
            return new Dimension(600, 300);
        }

        @Override
        public Dimension minimumLayoutSize(final Container parent) {
            return new Dimension(0, 0);
        }

        @Override
        public void layoutContainer(final Container parent) {
            if (parent.getComponentCount() != 2) {
                throw new RuntimeException("Supports for exact 2 components");
            }
            final Dimension size = getSize();
            final int widthForLeft = size.width * _leftPercent / 100;
            final int widthForRight = size.width - widthForLeft;
            final Component left = parent.getComponent(0); //left Component
            left.setSize(widthForLeft, 1);
            final Dimension leftDimension = left.getPreferredSize();
            left.setBounds(0, 0, widthForLeft, leftDimension.height);
            final Component right = parent.getComponent(1); //right Component
            right.setSize(widthForRight, 1);
            final Dimension rightDimension = right.getPreferredSize();
            right.setBounds(widthForLeft, 0, widthForRight, rightDimension.height);
            parent.setSize(size.width, Math.max(leftDimension.height, rightDimension.height));
            parent.setPreferredSize(new Dimension(size.width, Math.max(leftDimension.height, rightDimension.height)));
        }
    }
}

by wrapping main method into invokeLater() is possible to see :

enter image description here

SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            final SwingApp app = new SwingApp();
        }
    });
mKorbel
  • 109,525
  • 20
  • 134
  • 319
haferblues
  • 2,155
  • 4
  • 26
  • 39