What is your favorite layout?

As the title said, I’m wondering what is your favorite layout for building java app?

Usually, I use a tricky combination of BorderLayout and GridLayout with multiple panels. You can make mostly anything you want this way and the API of both layout is very simple so it only takes a seconds to understand it. But it never feel like it was suppose to be use like that :S.

I tried a couple of time to look at more fancy layout but they all seems over complicated while I can already do what I want with an easier api. The kind of layout I looked at are TableLayout, GroupLayout, GridBagLayout and maybe other don’t remember their name.

https://code.google.com/p/table-layout/
This is my project. It does table based layout for Swing, libgdx, Android, and TWL. I like the clear hierarchy and separation between layout and code that the DSL provides. However, the Java API has come a long way and is almost as easy to use, at the loss of the clear hierarchy. Unfortunately the Java API is lacking javadocs. I need to rewrite the docs on the main page showing the Java API first, then the DSL. The Java API for libgdx is up to date, but the bridges to support the other languages are slightly behind. It is mostly a matter of adding delegate methods to Table (see the libgdx Table class). If someone was using it for Swing I’d be inclined to update the other bridges, otherwise I’ll get to it eventually.

Well I had an idea about a Layout that would only require 3 simple command and you could create any layout that you want. But I wanted to ask around first to know if I was trying to reinvent the wheel or not.

But I decide to stop procrastinating and just code it. Here is the result :

The 3 commands are :

add(Component); //Add a component with his preferred size
addSpace(int); //Add a component with a fixed size specified by the int
addFill(double); //Add a component that fill the size not taken by the component with preferred size and fixed size

I create the 3 following layout in no time just to test it.

http://dl.dropbox.com/u/16471407/EasyLayout.PNG

@Nate : Yeah I looked at table layout a few times. It looks great but I could never motivates myself to learn it :S. The google page with the code I’m not used to kinda scared me.

I came to the same conclusion you did years ago Gudradain… You can do just about anything with BorderLayout, GridLayout, and BoxLayout (Box.create(Horizontal|Vertical)Box to make things just a smidgen more concise. Some folks will use GridBagLayout for everything, but I found that to be a little complex.

Yeah you can create anything. But never liked the syntax.

The layout I just created is greatly inspired by BoxLayout but for some reason I often get strange behavior with BoxLayout. My other inspiration was GroupLayout.

There is a difference between being able to describe a layout and it being an easy, pleasant experience. Trivial layouts are trivial with most layout managers. Also, I think there is a lot that can be done to separate code from layout. Laying out via code is powerful, but the flat, linear nature of it means you completely lose the hierarchy in the layout. If you’ve ever had to look at someone else’s GridBagLayout, you know what I mean.

Yeah, I need to do a better job describing how to use it concisely. I plan to rewrite the docs. It is really pretty easy to use once you understand the concept.

Aha! Your thread was a trap! :wink: Can you show the code for the layout screenshots?

I wrote once before that my favorite layout was “null” (aka “absolute”). But now I am mostly relying on nesting. No reason not to use a half dozen or more local JPanels with simple layouts nested within one another, afaik.

But if you like GridBag and wish it were easier to use, check out Horstmann’s Core Java. He has code online for a GridBagLayout helper that simplifies building (somewhat).

http://horstmann.com/corejava.html
In the 8th edition, it is in chapter 9: “GridBagLayoutTest”

[edit: Yes, figuring out JTable was a bear, took several hours of thrashing when I finally submitted. JList is a bit easier to use, and perhaps makes a good stepping stone. It also uses a “model” but is not as complicated as the JTable.]

Sorry :persecutioncomplex:

I redo the example that you can find in the Java tutorial on the site of Oracle. The 3 layouts are in order from GroupLayout, SpringLayout and CustomLayout.

Here is the code :

TestGroup


        public TestGroup(){
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		EasyPanel panel = new EasyPanel();
		frame.setContentPane(panel);
		
		panel.setLayout(new EasyLayout(EasyLayout.HORIZONTAL));
		
		EasyPanel panel1 = new EasyPanel();
		EasyPanel panel2 = new EasyPanel();
		EasyPanel panel3 = new EasyPanel();
		
		EasyPanel buttonPanel = new EasyPanel();
		EasyPanel buttonPanel1 = new EasyPanel();
		EasyPanel buttonPanel2 = new EasyPanel();
		
		panel.addSpace(10);
		panel.add(panel1);
		panel.addSpace(5);
		panel.add(panel2);
		panel.addSpace(5);
		panel.add(panel3);
		panel.addSpace(10);
		
		panel1.setLayout(new EasyLayout(EasyLayout.VERTICAL));
		panel1.addSpace(15);
		panel1.add(new JLabel("Find what:", JLabel.RIGHT));
		panel1.addFill(1);
		
		panel2.setLayout(new EasyLayout(EasyLayout.VERTICAL));
		panel2.addSpace(15);
		panel2.add(new JTextField());
		panel2.addSpace(5);
		panel2.add(buttonPanel);
		panel2.addSpace(5);
		
		panel3.setLayout(new EasyLayout(EasyLayout.VERTICAL));
		panel3.addSpace(13);
		panel3.add(new JButton("Find"));
		panel3.addSpace(5);
		panel3.add(new JButton("Cancel"));
		
		buttonPanel.add(buttonPanel1);
		buttonPanel.add(buttonPanel2);
		
		buttonPanel1.setLayout(new GridLayout(2, 1, 5, 5));
		buttonPanel1.add(new JCheckBox("Match Case"));
		buttonPanel1.add(new JCheckBox("Whole Words"));
		
		buttonPanel2.setLayout(new GridLayout(2, 1, 5, 5));
		buttonPanel2.add(new JCheckBox("Wrap Around"));
		buttonPanel2.add(new JCheckBox("Search Backwards"));
		
		frame.setVisible(true);
		frame.pack();
	}

TestSpring


        public TestSpring(){
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		EasyPanel panel = new EasyPanel();
		frame.setContentPane(panel);
		
		panel.setLayout(new EasyLayout(EasyLayout.VERTICAL));
		
		EasyPanel horPanel = new EasyPanel();
		
		panel.addSpace(5);
		panel.add(horPanel);
		panel.addSpace(5);
		
		EasyPanel panel1 = new EasyPanel();
		EasyPanel panel2 = new EasyPanel();
		
		horPanel.addSpace(5);
		horPanel.add(panel1);
		horPanel.addSpace(5);
		horPanel.add(panel2);
		horPanel.addSpace(5);
		
		panel1.setLayout(new GridLayout(4, 1, 5, 5));
		panel1.add(new JLabel("Name:", JLabel.RIGHT));
		panel1.add(new JLabel("Fax:", JLabel.RIGHT));
		panel1.add(new JLabel("Email:", JLabel.RIGHT));
		panel1.add(new JLabel("Address:", JLabel.RIGHT));
		
		panel2.setLayout(new GridLayout(4, 1, 5, 5));
		panel2.add(new JTextField());
		panel2.add(new JTextField());
		panel2.add(new JTextField());
		panel2.add(new JTextField());
		
		panel1.setPreferredSize(new Dimension(80, (int) panel1.getPreferredSize().getHeight()));
		panel2.setPreferredSize(new Dimension(150, (int) panel2.getPreferredSize().getHeight()));
		
		frame.setVisible(true);
		frame.pack();
	}

TestDiagonal


        public TestDiagonal(){
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		EasyPanel panel = new EasyPanel();
		frame.setContentPane(panel);
		
		panel.setLayout(new EasyLayout(EasyLayout.VERTICAL));
		
		EasyPanel panel1 = new EasyPanel();
		EasyPanel panel2 = new EasyPanel();
		EasyPanel panel3 = new EasyPanel();
		EasyPanel panel4 = new EasyPanel();
		EasyPanel panel5 = new EasyPanel();
		
		panel.add(panel1);
		panel.addSpace(5);
		panel.add(panel2);
		panel.addSpace(5);
		panel.add(panel3);
		panel.addSpace(5);
		panel.add(panel4);
		panel.addSpace(5);
		panel.add(panel5);
		
		panel1.addFill(0);
		panel1.add(new JButton("Bigger Button 1"));
		panel1.addFill(4);
		
		panel2.addFill(1);
		panel2.add(new JButton("Bigger Button 2"));
		panel2.addFill(3);
		
		panel3.addFill(2);
		panel3.add(new JButton("Bigger Button 3"));
		panel3.addFill(2);
		
		panel4.addFill(3);
		panel4.add(new JButton("Bigger Button 4"));
		panel4.addFill(1);
		
		panel5.addFill(4);
		panel5.add(new JButton("Bigger Button 5"));
		panel5.addFill(0);
		
		frame.setVisible(true);
		frame.setSize(300, 188);
	}

I don’t have a way currently to specify a minimum size and maximum size for an expandable component (a component that can grow or shrink) but I’m planning to find a solution for it. That’s why I used frame.setSize(300, 188) for TestDiagonal instead of frame.pack(). I had to find the correct size by guess and error. That’s the major flaw I find in it currently.

MigLayout is by far the best layoutmanager and the only one I use these days.

This is one thing I didn’t like about Swing. The only way I could even get GUIs to always line up elements perfectly, whilst also flowing exactly how I want to, I have to use BorderLayouts, BorderLayouts, BorderLayouts, and yet more BorderLayouts, all heavily nested within endless JFrames.

Occasionally I’ll use a Flow or Grid layout somewhere, but often it ends up getting switched out into lots more BorderLayouts.

Of course except that it isn’t. :slight_smile: It is very (overly?) complex, 200kb+, and doesn’t help separate layout from code. It also only works for Swing.

Here is some TableLayout DSL from an Android UI app:

align:top pad:4,6,0,8 
* fill:x expand:x 
{ 
	* space:5 
	[country:button] (pressed:button_flag_down normal:button_flag_up) 
	[numberText:''] width:0 expand:x fill:x (textSize:21 soundEffectsEnabled:false) 
	[contacts:button] padTop:2 (pressed:button_contacts_down normal:button_contacts_up) 
}
---
{ 
	[button_overlay_cart] padRight:6 
	[minutes:'42 minutes'] (textColor:'#329b01') 
	[settings:'Settings'] expand:x align:right (textColor:'#329b01') 
} pad:1,7,0,7 

Square brackets are named widgets (buttons, labels, etc). “button_overlay_cart” uses an image in the Android assets. TableLayout is generic but allows toolkit specific functionality like this. In libgdx you can reference images in an atlas this way, etc. Functionality like this can also be customized per application. Stuff in parenthesis are setting fields, bean properties, or calling methods. Parameters are automatically cast to the right types if possible. Strings, ints, booleans are obvious, but it can do more. Eg, “textColor:’#329b01’” finds the setTextColor method, knows the parameter is a color, and the Android TableLayout bridge knows how to convert that to a color. Also “pressed:button_contacts_down” on a View has special handling to set a StateListDrawable for R.attr.state_pressed. Equivalent code for this is a major PITA.

After the layout code above, the only code I need to write is mostly to get widgets by name and set listeners. You can also create your objects in code and reference them by name inside the DSL. It saves mixing object creation with layout, which makes for very clean code. Yes, Android has XML crap, but it is quite nasty, not extensible, and Android specific.

I list some other layout libs here:
https://code.google.com/p/table-layout/#Similar_libraries
I like DesignGridLayout a lot, though it is for a very specific type of layout. Using canonical grids, the amount of code needed to layout is amazingly small.
http://java.net/projects/designgridlayout

Okay okay, I’m finally going to break down and try TableLayout. ;D I’m slightly crazy in that I heart Swing, but never really used layouts other than the built-in ones. Tried MigLayout for awhile, but as Nate said, a little heavy and unintuitive to me. Maybe I didn’t give it long enough to sink in though.

Hahaha I have the impression you are talking about me here :slight_smile:

@Nate I’m curious. How would your TableLayout code look like for the 3 layout I post? (Just if you have time to do it)

EDIT : Or give me a something you already create with your TableLayout and I will try to implement it so we can compare the code. (Don’t post something over complicated with over 30 different widget. I won’t do it)

I also use MigLayout a lot. I wouldn’t go as far as to claim it’s the best (whatever that means! :slight_smile: ), but your response is full of inaccuracies.

[quote]It is very (overly?) complex
[/quote]
I could have almost agreed with you on this, but then you posted the TableLayout example! :wink: You really believe that’s less complex??? The constraints actually seem very similar, but TableLayout is more verbose (not meant as a criticism - there’s a lot I like about it).

[quote]200kb+
[/quote]
The standard layout bundle for Swing is 75kb!

[quote]doesn’t help separate layout from code
[/quote]
This is a matter of opinion, but personally I think it does, mainly because it removes the need for nested components purely for layout purposes. Nested components should be used for logical, not appearance, purposes. Yes, it does involve (usually) having your layout constraints within the Java source, but I don’t think that’s a bad thing.

To use a parallel example - I do a lot of work with the NetBeans platform, which uses XML files for lots of system configuration purposes. Over the last few years there’s been a concerted effort to write these XML files from compile time annotations in source files, primarily because keeping the logic in two (or more) different places has proven to be a PITA to work with in practice. It’s much easier to see everything within one file.

[quote]It also only works for Swing.
[/quote]
Huh? And SWT, JavaFX (1 & 2), Android, Amino … and that’s just what I’ve come across. Almost all the MigLayout code is toolkit neutral.

I’m a big fan of BorderLayout and GridBagLayout, but the Netbeans editor just rocks everything.

In .NET WPF, XAML is just perfect: it can be directly edited by hand and nevertheless provides very nice results in a minimum amount of time, not to mention the easy use of the MVVM pattern. I never found anything equivalent in Java. Even data-binding is a lot more messy to use. Therefore, I’ve no regrets to give the control of my UIs to automated tools like the Netbeans editor (Matisse).

Time-to-market plays an important role in the choice of libraries/tools…

Cool! The libgdx TableLayout bridge is the most up to date, as I use it at work almost everyday. The Android bridge is also pretty up to date, as I have an app using it. If you are going to try it out for Swing, I would love to clean up the Swing bridge first! I’ve also been meaning to write better docs. Maybe I’ll get to it tonight.

I did have a few things incorrect (see below), sorry. I didn’t mean to come off the wrong way, MigLayout does a lot and is probably a nice lib. I am personally put off by the constraint complexity, and also I think a DSL can greatly improve readability. I’ll explain below.

I could have almost agreed with you on this, but then you posted the TableLayout example! :wink: You really believe that’s less complex??? The constraints actually seem very similar, but TableLayout is more verbose (not meant as a criticism - there’s a lot I like about it).
[/quote]
Yes, it is less complex. The constraints are align, fill, expand, pad, space, size, colspan, uniform. I’d like to see you list the MigLayout constraints in a sentence! :stuck_out_tongue: I posted a complex example to show off features. The example is doing more than layout, it does widget creation of buttons and labels and has fields and bean properties being set, and methods being called. I’ll post some less complex examples of Gudradain’s layouts.

The standard layout bundle for Swing is 75kb!
[/quote]
Standard layout bundle? Ahhh, I was assuming the 198kb JAR was required to use MigLayout, but it appears the 75kb JAR is sufficient for use with Swing. I will update the Similar Libraries section of the TableLayout docs. FWIW, TableLayout for Swing is 68kb. This is due to the DSL parser, if only using the Java API it is 29kb.

This is a matter of opinion, but personally I think it does
[/quote]
I don’t think we are talking about the same thing. What I mean is that by laying out in code, it is often a mess. If widget creation is mixed with adding things to the layout, it is very hard to read. This is easily fixed by creating all your widgets, then adding them to the layout. However, the code that does layout still doesn’t show the entire layout hierarchy. For complex layouts, especially where things are nested, this makes it very difficult to read. Eg, can you seriously look at this layout and have some idea what it does right off the bat?

JPanel p = createTabPanel(new MigLayout("", "[]15[][grow,fill]15[grow]"));
p.add(list1, "spany, growy, wmin 150");
p.add(new JLabel("Last Name"));
p.add(new JTextField());
p.add(new JLabel("First Name"), "split");
p.add(new JTextField(), "growx, wrap");
p.add(new JLabel("Phone"));
p.add(new JTextField());
p.add(new JLabel("Email"), "split");
p.add(new JTextField(), "growx, wrap");
p.add(new JLabel("Address 1"));
p.add(new JTextField(), "span, growx");
p.add(new JLabel("Address 2"));
p.add(new JTextField(), "span, growx");
p.add(new JLabel("City"));
p.add(new JTextField(), "wrap");
p.add(new JLabel("State"));
p.add(new JTextField());
p.add(new JLabel("Postal Code"), "split");
p.add(new JTextField(), "growx, wrap");
p.add(new JLabel("Country"));
p.add(new JTextField(), "wrap 15");
p.add(createButton("New"), "span, split, align left");
p.add(createButton("Delete"), "");
p.add(createButton("Edit"), "");
p.add(createButton("Save"), "");
p.add(createButton("Cancel"), "wrap push");

Of course not, you would have to read each constraint and mentally construct the table to have some idea of the layout. This is exactly the reason why GridBagLayout is such a PITA! Sure, have a DSL for each widget makes it somewhat easier to read (after the sharp MigLayout learning curve), but fundamentally it is the same issue.

The idea for TableLayout was to try out having a DSL for the entire layout. It has worked out pretty ok. At first glance it is relatively easy to see the layout structure (after the TableLayout learning curve). You still have to mentally parse the DSL, but the DSL a limited number of constraints does make this easier. This has been done many times before using XML, but it just gets in the way too much.

I’ve found sometimes you need to layout in code, eg with a complex layout that has many pieces configured differently based on some application state. The TableLayout Java API has recently seen some love. It uses method chaining rather than the DSL. It is almost as concise, but readability suffers somewhat.

I added widget creation, field/property setting, and method calling to the DSL, but I have some mixed feelings about it. While it can move some layout related stuff out of your code and into the DSL, it also makes the DSL a bit more complicated. This can largely be ignored, but I wonder if it would be better to go back to only layout.

[quote], mainly because it removes the need for nested components purely for layout purposes. Nested components should be used for logical, not appearance, purposes. Yes, it does involve (usually) having your layout constraints within the Java source, but I don’t think that’s a bad thing.
[/quote]
With more powerful layout managers, fewer components are usually needed and this is a good thing, but I’m not too worried about using components for layout.

[quote]To use a parallel example - I do a lot of work with the NetBeans platform, which uses XML files for lots of system configuration purposes. Over the last few years there’s been a concerted effort to write these XML files from compile time annotations in source files, primarily because keeping the logic in two (or more) different places has proven to be a PITA to work with in practice. It’s much easier to see everything within one file.
[/quote]
Agreed. I only move a layout to a separate file if it gets complex enough to warrant the separation. For simpler layouts, I either use the DSL with strings or the Java API. Using strings is a bit nasty. I really wish Java had a verbatim string! It would help so much! Here is how it currently looks:

table.parse("align:top pad:4,6,0,8"
	+ "* fill:x expand:x"
	+ "{"
	+ "  * space:5"
	+ "  [country:button] (pressed:button_flag_down normal:button_flag_up)"
	+ "  [numberText:''] width:0 expand:x fill:x (textSize:21 soundEffectsEnabled:false)"
	+ "  [contacts:button] padTop:2 (pressed:button_contacts_down normal:button_contacts_up)"
	+ "} --- {"
	+ "  [button_overlay_cart] padRight:6"
	+ "  [minutes:'42 minutes'] (textColor:'#329b01')"
	+ "  [settings:'Settings'] expand:x align:right (textColor:'#329b01')"
	+ "} pad:1,7,0,7"
);

Definitely not as good as a verbatim string or separate file. :frowning: I’ll post some Java API examples below for comparison.

[quote]Huh? And SWT, JavaFX (1 & 2), Android, Amino … and that’s just what I’ve come across. Almost all the MigLayout code is toolkit neutral.
[/quote]
I was wrong about it only being Swing, sorry!

Sure, but you have to post your code for your layouts! :slight_smile: Your image:

http://dl.dropbox.com/u/16471407/EasyLayout.PNG

First window:

* space:6
'Find what:' align:top
{
	* align:left space:6
	[findEdit] colspan:2 fill
	---
	[matchCaseCheckbox] [wrapCheckbox]
	---
	[wholeWordsCheckbox] [backwardsCheckbox]
}
{
	* space:6
	[findButton]
	---
	[cancelButton]
}

To read it, stuff after “*” sets the default properties for all cells. The outer table is 3 columns: a label, table, and another table. The “—” denotes a new row. Stuff in square brackets references named widgets. The “align:top” and “align:left” could also be replaced by just “top” and “left”. You can paste this code into the TableLayout editor to see it rendered:
http://table-layout.googlecode.com/svn/wiki/jws/editor.jnlp

Second window:

* space:6
| align:right | expand:x fill
'Name:' [nameEdit]
---
'Fax:' [faxEdit]
---
'Email:' [emailEdit]
---
'Address:' [addressEdit]

The pipe character “|” is for setting default properties for all cells in a column, which is useful for forms. Being able to create labels without any code is very convenient!

Third window:

* expand:x align:left
[button]
---
[button] padLeft:20%
---
[button] padLeft:40%
---
[button] padLeft:60%
---
[button] padLeft:80%

Ok, I showed you mine, now show me yours! :smiley:

A real ariste writes his layout code by hand! :wink: Just kidding, I’ve used the WYSIWYG tools in many projects. It’s the only way to use GridBagLayout! They are great when they work, but I’ve found they break down with customized components and very complex UI.

@Nate Nice, really like the editor that change in real time how the layout look when you change the code. And the code is pretty short to do those layout. I only have a few remarks :

  1. We can’t see the window in which the components are layout
  2. The button in the first example need to be push up a little to make it look better
  3. There should be some space before the label in the second layout
  4. The buttons in the diagonal layout should go one under another if you shrink the window (that is not the case currently). Is it possible with TableLayout?
  5. The code that show how to interract with those layouts in your java code is not present so I guess that explain why the size is so much smaller.

[quote]Sure, but you have to post your code for your layouts!
[/quote]
It’s already in a post below.

Do you mean the source code for my EasyLayout class?