The Source for Java Technology Collaboration
User: Password:



Ethan Nicholas

Ethan Nicholas's Blog

Reinventing GridBagLayout

Posted by enicholas on April 20, 2006 at 10:51 AM | Comments (13)

Java suffers from a layout crisis. It ships with a bunch of poorly-thought-out layout managers, a few (like GridLayout and BorderLayout) that are decent within their limited niche, and... GridBagLayout. Despite a few warts, GridBagLayout is powerful enough to handle almost any layout task -- but it's so ridiculously difficult to use that most programmers avoid it like the plague.

There have been many attempts to replace GridBagLayout, with varying degrees of success (TableLayout, SpringLayout, GroupLayout, and FormLayout, just to name a few) but from what I have seen, most people just drop back to using simpler layouts, like BoxLayout, in nested panels. This is a bad idea. For one thing, it complicates component setup and makes rearranging the UI and controlling resizing behaviors much more difficult. For another, it results in many additional components. A setup that could be done with a single GridBagLayout might take four or more panels with simpler layouts -- and every extra level of nesting is another level that has to be processed during repaints, event handling, and layout, not to mention the unnecessary memory consumption. Memory and performance are already at a premium in Java, so you can ill-afford to create more components than necessary to get the job done.

GridBagLayout isn't fundamentally a bad layout manager -- it's just too hard to use. If it were simpler, I don't think most of the "GridBagLayout replacements" would have a reason to exist, as there is very little that GridBagLayout can't do. While building the JAXX user-interface language, I needed a powerful, easy-to-use layout system, and (perhaps surprisingly) I settled on GridBagLayout.

JAXX offers a Table component which is built on top of GridBagLayout. I briefly mentioned Table in my introduction to JAXX, but didn't go into any details. The goal of the <Table> tag was to offer all of GridBagLayout's power, while removing the tedium and error-prone-ness (error-prone-itude?) that characterizes more typical GridBagLayout usage. Take a look at a simple table:

<Table>
  <row>
    <cell><JLabel text='Username:'/></cell>
    <cell><JTextField id='username'/></cell>
  </row>
  
  <row>
    <cell><JLabel text='Password:'/></cell>
    <cell><JPasswordField id='password'/></cell>
  </row>

  <row>
    <cell columns='2'>
      <JPanel layout='{new GridLayout(1, 2, 6, 6)}'>
        <JButton text='OK'/>
        <JButton text='Cancel'/>
      </JPanel>
    </cell>
  </row>
</Table>

Here's what it looks like when run:

GridBagLayout isn't perfect, of course -- I needed to use a sub-panel to get the buttons right -- but that was sure better than coding GridBagLayout by hand, wasn't it?

JAXX's Table tag offers a lot more features, like the ability to specify GridBagConstraints attributes on each <cell>:

<cell weightx='1' fill='horizontal'><JTextField id='username'/></cell>

You can also specify constraints on a <row>, in which case they apply to each cell in the row (unless overridden). You can even specify default constraints for every cell by putting them on the <Table> tag itself:

<Table insets='3, 3, 3, 3' anchor='northwest'>

Table-level defaults can be overridden on either a per-row or per-cell basis.

I think that JAXX's <Table> tag breathes new life into the much-maligned GridBagLayout, allowing it to flex its power while removing (most of) the cursing that using GridBagLayout typically entails. Eventually JAXX will offer specialized support for other advanced layout managers, like FormLayout, but for the time being GridBagLayout is surprisingly powerful when it isn't hampered by the manual constraints wrangling of days past.

For more information on JAXX, take a look at www.jaxxframework.org.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • GridBagLayout has fundamental layout problems. It is not powerful handle almost every layout task. There are essential layout tasks that GBL doesn't address.

    A general GBL form won't comply with the MS Layout Specifications and Guidelines. So with GBL you can hardly compete with a native Windows app at the layout level.


    GBL lacks a means to group columns and to get row heights that are independent of the row content. The line height in a newspaper is independ of the characters in that line. GBL makes it hard to balance design. It lacks a means to make three forms consistent. It cannot ensure a minimum size. And in general, it won't retain proportions if the hardware resolution (dpi) or font or font size changes! All which I consider essential for everyday design, not the average Java layout.


    Here's a short PDF with everyday design tasks that the GBL can't do: http://www.jgoodies.com/articles/layout-essentials.pdf The JGoodies Forms Demo shows layout tasks that GBL can't do, several of them taken from the MS Layout Specifications and Guidelines. I compare the power of layout managers at the end of the Forms whitepaper: http://www.jgoodies.com/articles/forms.pdf For example, SpringLayout is very powerful, ExplicitLayout is powerful, FormLayout is quite powerful, HIGLayout is quite powerful, GBL is weak.


    As you show, there are techniques that make GBL easier to read, to understand, to write and to maintain. The fundamental layout problems remain.


    -Karsten

    Posted by: karsten on April 21, 2006 at 02:00 AM

  • Personally, I say let GridBagLayout die. It's a pain in the neck to use, especially if you're having to write XML to make it work. Try something more advanced like JCommon's TableLayout:
    JCommon Project

    Posted by: sunsett on April 21, 2006 at 07:52 AM

  • Well said Karsten. We don't need to reinvent GridBagLayourt - we need to officially replace it.
    It's about time Sun adopted one of the better layout managers and sponsored it's support in Visual Designers so that it can be used as easily graphically as it is in code. (I thought that this was what SpringLayout was intended for, but we need a layout manager that's as easy to use in code as it is in a Visual Designer.)
    I have used the TableLayout and found it quite straight forward. I think it would easily translate to an HTML-like descriptor language if that's the way you are inclined.
    However, any of the managers mentioned by Karsten would, I'm sure, be an improvement on what we have 'out-of-the-box' in the JDK. Sun just needs to get behind the best one and endorse its use.
    And to the author, Ethan - by building an XML descriptor framework and basing it on the GridBagLayout you are just making the legacy worse, IMO. Too much time has been spent already on feeding the monster. Let it die.
    [Sorry there are no line breaks - this web app breaks when I include more than one br... Ouch!]

    Posted by: red3 on April 21, 2006 at 10:14 AM

  • red3, I think you're referring to the popular TableLayout, but the one with JCommon is actually a completely re-designed layout manager based on all the properties of an HTML table but able to be utilized programmatically. There is even a TablePanel that can optionally encapsulate it and offer the ability to add cell borders and other neat features.

    Posted by: sunsett on April 21, 2006 at 01:13 PM

  • Thanks for clearing that up. Yes, I am referring to the 'other' TableLayout than you.

    Posted by: red3 on April 21, 2006 at 01:28 PM

  • whatever they layout gets addopted as thew new "standard" one, i'd like to get a standard (sanctioned by a JSR) XML description for it, support for this XML in IDEs, and a standard API to render this XML at run-time. Most Java developer's can't even imagine the ease of development and maintenance that comes with Gnome's Glade and LibGlade because they choose to use XML description from the start up.

    Posted by: flozano on April 22, 2006 at 07:07 AM

  • Assuming you're not Karsten, and you don't have too advanced needs, the gridbag layout is fine. The only real problem with is that the constraints for each component are expressed as long sequences of integers. Magic values are not a good vehicle for modelling concepts like of position, size, padding, weight, fill, insets and anchoring. To make it worse, they're mostly all in the same range. It's an API problem, not a technical one.

    Simple object-oriented tricks allow us to wrap it in a more readable (and maintainable) API:


    filePanel.add(aboutButton, GBConstraints.create
    (GBConstraints.pos(0, 0),
    GBConstraints.size(1, 1),
    GBConstraints.fill(GBConstraints.NONE),
    GBConstraints.insets(2),
    GBConstraints.weight(0, 0)));


    You can more easily write - and read! - the gridbag properties for this component. It's not hard to write the GBConstraints class either, so I leave that as an exercise. Once you have mastered the gridbag layout properly, you will find it is sufficient for most tasks, and likely never go back to the flow layout again :-)

    Kjetil

    Posted by: valstadsve on April 22, 2006 at 08:22 AM

  • In 1996, I created a new API using the GridbagLayout called Packer. It's been used by hundreds if not thousands of developers since that time. I've had the project out on the web for some time. You can find it at http://packer.dev.java.net.

    Some of the things that Karsten highlights in the jgoodies manifesto, are interesting, but not impossible to do with GridbagLayout.

    What Karsten didn't like was the API for GridbagLayout, it seems to me. The power is there to make it do most everything he highlights as a problem. You can use Insets to manage whitespace around the component. There are other things you can do to manage the horizontal alignment of fonts by injecting insets as the component comes into the layouts control.

    The Packer class can manage alot of these things. I just haven't thought it was really that important for my users. None of them tell me it is anyways.

    Posted by: greggwon on April 22, 2006 at 08:30 AM


  • For those that haven't tried my 1996 recast of the GridbagLayout API, check out http://packer.dev.java.net. It provides a much simplier coding style that makes using GBL a breeze.


    The issues that Karsten covers on why he did JGoodies is interesting. I've never been bothered by font alighnment of labels vs fields. It's certainly possible to make that happen with Packer since it could mediate the addition of each component, and do some row alignment management using Insets.


    I've just not had a lot of comments about misaligned rows to encourage me to do that.

    Posted by: greggwon on April 22, 2006 at 08:45 AM

  • Ahh, I didn't notice it was putting the comments at the top of the list.

    Posted by: greggwon on April 22, 2006 at 08:47 AM

  • when you run out of stream with simpler layouts and then use more powerful ones, you end up a dogs breakfast of layout managers leads -- i think swing developers should bite the bullet, make best friends with GBL, possibly use a derived Gbc.java class to simplify for their purposes as in Joshua Bloch's Effective Java book (and see such a class Gbc.java in aptframework -- shameless plug)
    and just stick to GBL, using spacer panels and subpanels -- who cares about memory and extra components -- i wouldn't assume its a bottleneck and i wouldn't pre-optimise without quantifying the cost of the "bottleneck". By the way in
    aptframework, i use annotations to configure Gbc's of components - very gimicky innit. Of course if using GUI builder ie. netbeans, then of course matisse/GroupLayout is all one should use -- but if coding the GUI, then love Gbc and it'll love you

    Posted by: evanx on April 24, 2006 at 01:58 AM

  • One technique I have used succesfully with GBL is Organize and Conquer. See if you like it:

    GridBagLayout simplified ?

    Posted by: sandipchitale on April 29, 2006 at 11:49 PM

  • I tried to use GridBagLayout in a package I wrote to simplify the creation of Java/Swing form-based applications called JComponentBreadboard


    After trying many things that ALMOST made GridBagLayout do what I wanted, I finally in effect wrote a new layout manager inspired by GridBagLayout, but minus all the quirks and confusion; this layout manager is what my product uses for all of its layout management needs.

    Why JComponentBreadboard's layout manager works better than GridBagLayout:


    You specify the layout using a simple 2-D array. Makes sense, use an array to specify a grid-based layout, right? No more constraint objects to mess with.

    There are no confusing weights. Instead, for each row and column
    you define two boolean attributes: one for if you want the row/col to scale up to soak up extra space in the parent, and a second if you want it to scale down when parent space is tight. Scaling is always uniform across rows/columns that are being scaled. Initial sizes are derived from the preferred size of the JComponents in the row or column. Works really well, without any fuss.

    Lots of nice little static wrapper functions that attach things like alignment directives as special client properties of the JComponents they apply to. So you can just say more or less directly if you want something to be left or right aligned in the cell, etc.

    If you are interested in exactly how this layout manager works, the algorithm is fully described in
    JComponentBreadboard's setBreadboard method's javadocs. Or if you don't like reading detailed specs, check this

    simple
    example from the JComponentBreadboard User's Guide
    that explains how the layout manager works.

    John Gunther, JComponentBreadboard author.

    Posted by: johngunther on August 03, 2007 at 01:42 PM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds