Dynamic layout with expandable cells

I am really stuck with a layout that I have to do with java swing.

I need to create a dynamic form, iterating through a vector of labels and input components.

Here's how it should be:

enter image description here

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

I tried GridBagLayout, which worked pretty well, but as you can see in the first line in the picture, the shortcut can be very long. So I used JTextarea, but GridBagLayout disabled it. I also studied JGoodies FormLayout, but also had problems with Textarea for long shortcuts.

The ratio of 25/75 and 75/25 is not so important, but in fact it is also part of what I should do.

I think it is just very difficult to get Textarea to expand its parent component.

I also read / wrote these notes:

but I'm still stuck.

Do any of you have any ideas on how to do this?

thanks

+4
source share
2 answers

It has been a long time since I did a lot of Swing, but two thoughts:

  • If the control is disabled, it sounds like you are not setting a minimum size.

  • I don’t think that one of the ready-made layout managers has the ability to maintain aspect ratio, for example, your 25/75. But do not despair! You can write your own layout manager. Back when I did a lot of Swinging, I wrote several layout managers. (I would say "for special requirements", but in fact they were for quite general requirements, and he always surprised me that Java did not include ready-made layout managers to handle such things. For example: you often need a string or a button column where all buttons have the same size, so you need to find which button has the longest text, and then resize all the others so that they fit in. Or: set the rows and columns where each column size will be the largest in this column, but the width of one s olbtsa does not affect the other columns, and then similarly for the lines.) In any case, what you describe is quite unusual, so you can just write your own layout manager.

The trick to writing a layout manager is to implement several key functions: (a) calculate the X and Y coordinates where you will place each control, given the total size; (b) Calculate the required minimum size; c) calculate the preferred size; (d) Calculate the maximum size that you will use. Umm, maybe I forgot one or two more, but that’s not so important. When I first thought of “writing my own layout manager,” it sounded like “write your own database engine” or “write your own compiler first,” but that’s not so close to this scary thing. This is usually a few hundred lines of code.

Of course, if someone else here tells you how to do what you want to do with one of the ready-made layout managers, it's a lot easier.

+1
source

Here is what I got so far. This example uses only JTextArea , but it also works with other components (like my images). The only thing he cannot do at the moment is to compose the components, as in line 3 in the figure above (one on top of the other), but this should not be a problem.

Perhaps this helps someone learn how to write their own 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 the main method in invokeLater() you can see:

enter image description here

 SwingUtilities.invokeLater(new Runnable() { @Override public void run() { final SwingApp app = new SwingApp(); } }); 
0
source

All Articles