 |
Group Layout Therapy
Posted by evanx on November 30, 2006 at 06:09 AM | Comments (15)
We use GroupLayout
to assemble simple subpanels.
For complicated forms, programming layout becomes (very) difficult,
and so it's saner to use a GUI designer such as Netbeans.
Click here to read "Group Layout Therapy, a psychological drama"
A part of "Gooey Beans, a trilogy in 42 parts"
Demo
Our Address Form is in play again.
(AddressForm, 150k/400k, unsandboxed, Java6)
Code glance
We configure our component properties in AddressFormPanelProperties
so that AddressFormLayoutPanel below is relatively neat.
public class AddressFormLayoutPanel extends JPanel {
AddressFormPanelProperties properties =
dependencyContainer.getInstance(AddressFormPanelProperties.class);
public AddressFormGroupLayoutPanel() {
initComponents();
}
private void initComponents() {
addVerticalPanel(
createHorizontalPanel(
createInputComponentPanel(properties.firstName, firstName),
createInputComponentPanel(properties.lastName, lastName),
createInputComponentPanel(properties.email, email, true),
createInputComponentPanel(properties.phone, phone)
),
createHorizontalPanel(
createInputComponentPanel(properties.address1, address1, true),
createInputComponentPanel(properties.address2, address2, true)
),
createHorizontalPanel(
createInputComponentPanel(properties.postalCode, postalCode),
createInputComponentPanel(properties.city, city),
createInputComponentPanel(properties.state, state, true),
createInputComponentPanel(properties.country, country),
createInputComponentPanel(properties.postable, postable)
)
);
}
...
private JTextField firstName = new JTextField();
private JTextField lastName = new JTextField();
private JTextField phone = new JTextField();
private JTextField email = new JTextField();
private JTextField address1 = new JTextField();
private JTextField address2 = new JTextField();
private JTextField city = new JTextField();
private JTextField state = new JTextField();
private JTextField postalCode = new JTextField();
private JComboBox country = new JComboBox(new Object[] {"South Africa", "Zimbabwe"});
private JCheckBox postable = new JCheckBox();
}
where createInputComponentPanel() creates a subpanel with an input component
and it's label above it.
Punchline
Our AddressFormLayoutPanel and its AddressFormLayoutPanelProperties
is delibrately interchangeable with a form produced using Netbeans' GUI designer
so that we can choose to program our form view as above, or otherwise
design our form using Netbeans.
Sneak Preview
The next step is beans binding for our form, woohoo!
Our Presentation Model
class is a separate testable class which we bind
to our form. Our controller is also implemented
as a separate class, which interacts with the components in our forms,
and of course our presentation model beans.
So to summarise, our MVC architecture consists of the following.
-
View classes eg. produced using Netbeans GUI designer.
-
Presentation Model classes which can be developed using TDD.
-
Controller class which implements event listeners
and manipulates the view and model.
We provide beans binding support,
so that the controller can conveniently invoke a single method to update a
presentation model from a form, and visa versa.
The controller needs to manipulate the components in the view eg.
setEnabled(), requestFocusInWindow() et cetera.
Since Netbeans makes our components private to the form, we
provide proxies that are bound to the actual components using reflection.
We call them "adapters" because they give JTextField, JComboBox et al,
a unified interface eg. QInputComponent. These adapters support the binding
of the components to the presentation model.
Separating the view and controller in this fashion is fairly tedious,
but hopefully enables separation of concerns, and improves
testability eg. where we can mock up our view
to facilitate the test-driven development of our controller. This
is something i know nothing about, but i suspect is well important!?
Anyway, here is a sneak preview.
(PersonInfo, 150k/400k, unsandboxed, Java6)
You can refresh the "BeanInfo" tab (and also the "Console" tab) to see that the
values entered into our form are written to our Presentation Model.
In this demo, we use QLayout which is GroupLayout therapy for simple subpanels.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
What's with the unsandboxness?
Posted by: tackline on November 30, 2006 at 07:39 AM
-
if i don't have all-permissions, reflection doesn't work...
i really wish i knew how to configure webstarts so that they can use reflection, but of course can't access local filesystem, or open network sockets, or wha'ever, and/or one can check/uncheck what webstart can and can't do, eg. reflection is fine, but filesystem et al, no ways
if there is a way to do this, please lemme know :)
Posted by: evanx on November 30, 2006 at 07:46 AM
-
If a layout manager requires you to (a) use so many 'subpanels' and (b) build an elaborate infrastructure around it in order to use it without going insane, I would dump the layout manger.
Posted by: varan on November 30, 2006 at 09:23 AM
-
I think all other Layout Managers in the Address Book shootout had cleaner code than this... :)
Posted by: mikaelgrev on November 30, 2006 at 12:22 PM
-
My question in OConnor's blog regarding GroupLayout as to what advantage one gains from using it since the code for all other layouts appears to be considerably simpler remained unanswered.
GroupLayout has some nice ideas, but I think they are not quite flushed out, and that is why you see attempts, as in the Evan's blog here, to build some scaffolding around it to make it useable.
Posted by: varan on November 30, 2006 at 01:58 PM
-
Gl has built-in support in a major IDE and has built-in support for baselines. I'd say it's not meant for the human eyes (much as .RC files in Visual Studio or .xaml in Vista). If all you need to do is throw up a little prototype or a simple panel, why impose a new API on the developers to learn. I know, i know, we should all know exactly what's going on in there, but at the end of the day, if it's one less thing off my plate to worry about, i don't mind. Now, if only Matisse stopped being so stubborn in rearranging stuff for me and being too clever at guessing what i'm trying to do, it'd be just perfect for the job.
Posted by: kirillcool on November 30, 2006 at 05:09 PM
-
Reflection does work in the sandbox. It just can't do insecure things. If it could, you could use reflection to clear the security manager. It's similar to JNLP's j2ee-application-client-permissions which gives the malicious code enough room to grant itself full permissions.
Posted by: tackline on December 01, 2006 at 08:12 AM
-
i'm doing a field.setAccessible(true) on the JTextField's et al in the form because these are private eg. using Netbeans. Ordinarily i would have them package private and then reference them explicitly. However, i think that there might be value in decoupling the controller and the view (and binding it at runtime using reflection), besides the obvious value in supporting Netbeans forms. Eg I want to try a factory to create test-enabled mocks of the view's components, ie. to simulate the user entering certain values and pressing buttons, to write tests for the controller. But i haven't given that much thought. Anyway the main motivation is to support Netbeans forms, and provide support for Presentation Model for those, aka beans binding.
Posted by: evanx on December 01, 2006 at 08:58 AM
-
Those are some sweet looking forms. They definitely prove GroupLayout's unique worth. I doubt any other layout manager could misalign so many components using so little code.
Posted by: josgood on December 02, 2006 at 01:34 AM
-
They are misaligned, because i specified different sizes for the fields. If you want
them aligned, that's easy, just specify each field as being 100 pixels long ;)
Even better, design the form using Netbeans Matisse.
I'll write a mini-essay here on function vs form, excuse the pun.
I might copy this into a blog entry later (although i have
blogged on it before).
"Desktop Java" is a wide term. The "Desktop Java" i'm interested in
is "business information systems" and in particular "database frontends."
Think SAP and you're getting the idea.
Compared to writing a "desktop app" like, i dunno, iTunes,
or a personal productivity app like Thunderbird,
this is a different discipline.
So our app might be database application with a few hundred data entry screens
and query screens and such like. Our users are wanting new screens, and changes
to old screens, and changes to new screens you've just finished, and changes to
spec'ed screens that you haven't got around to implementing yet,
or are in the middle of implementing, or are never going to implement
but don't know it yet, because priorities and requirements are changing every day.
Given this situation, you want to build new screens as quickly as possible,
that satisfy the functional specs, and even more importantly, have them easy
to change later eg. next week eg. add more fields, and change the validation and business logic,
because the spec is here today, gone tomoro
If it's gonna take twice as long to make it a bit more beautiful, then you are not
gonna make it a bit more beautiful, today. Otherwise you are gonna fall behind and look slow.
Later you might get tasked specifically to beautify some screens,
ie. allocated the time and top priority. But that is probably never gonna happen
(unless they really are butt ugly), because there will always be higher priority tasks,
like urgent changes to the business functionality, rather than the beautification
of a screen that's bound to change later anyway, or maybe hardly be used compared to some
other screens.
In terms of the layout, the most important thing for a data-entry field is it's preferred
width. For instance, entering someone's surname into a text field that is 10 pixels
wide is gonna make the system testers laugh at you. Similarly having a
phone number field that is 400 pixels wide is equally silly.
Having said all this, there are going to be screens that are relatively complex,
and that we want to design using Netbeans Matisse, if not all of our screens.
But we want to use the Presentation Model pattern, MVC architecture,
and we want to move towards TDD. Can we have it all? Yes, we sure as hell gonna try! :)
Posted by: evanx on December 02, 2006 at 05:12 AM
-
Well, if you start with the premise that whatever Layout Manager the Netbeans Matisse uses has to be ipso facto great because Matisse is such a beautiful and useful tool, there is no argument.
But your defense, such as it is, is quite weak on any other grounds.
Posted by: varan on December 02, 2006 at 09:44 AM
-
Evan, I don't understand you argument. If you want to make changes fast using manual coding then for sure GroupLayout is surely the wrong choice? I your were using Matisse I would understand you better.
Posted by: mikaelgrev on December 02, 2006 at 09:47 AM
-
varan, i'm as happy using Gbc as i did before in the methods presented, ie. createInputComponentPanel(), createVerticalFlowPanel(), createHorizontalFlowPanel(). For hand coding forms i use methods such as these to stack subpanels, without any concern for what layout manager is being used behind the scenes. But certainly GroupLayout is appealing cos it's "hot."
I want to have the freedom to hand code and/or use Netbeans, and switch between, eg. the prototype might be a quick hand coded (simple) form, but later i might wish to switch to using a GUI designer eg. when the user requests a fairly complicated form and/or specific layout.
As you might have guessed, i am a Netbeans user, and to be honest, i haven't tried any other GUI designers, and to be honest, i don't expect to.
Mikael, i confess my experience of layout managers to pretty much limited to GBL, so i'm the wrong person to make the right choice ;)
For years i used LaTeX tables, and then HTML tables, and so translating a design into a grid is second nature for me. Making friends with GroupLayout is hard for me from that point of view, compared to Gbc. But at some time, one has to decide on a path, rightly or wrongly, and stick to it. I have made the decision with GroupLayout recently, and with Netbeans a year or so ago, and i'm living very happily with that choice.
Posted by: evanx on December 02, 2006 at 11:33 AM
-
Evan, I have a confession. I was a big GBC junkie just a few months ago and have been one for far too many years. Grid is also second nature to me however the bugs and inflexibility of GBC finally pushed me to writing my own layout manager (Mig Layout).
It turned out that this LM can do anything that GBC can and a lot more. It also can do anything that FormLayout can and also BorderLayout and a lot of (if not all) that SpringLayout is capable of. I simply collected all functionality into one LM.
I have used Matisse with the latest versions of netBeans and it is OK. Not more. Prototyping is great but components jump around too much and it is hard to attach components to the correct surface if you have a non-trivial layout. I'd say that I might need more practice but it's not like sliced bread.
GroupLayout for manual coding though, is a bad idea. Trust me on this. I would recommend just about any LM, including GBC, when it comes to manual code layout. GroupLayout has one purpose, to be written by an automatic layout tool like Matisse.
It doesn't sound like I can convince you to change now that you've made your choice but when you say those "%$&ยค%" words out loud later on, think of this blog. ;-)
Cheers,
Mikae
Posted by: mikaelgrev on December 02, 2006 at 01:40 PM
-
I think the whole thread started because of the title of the page, which suggests you are trying to solve a problem, and we all know that the problem need not be solved because it is easily avoided by using something else.
I hate to knock GroupLayout so much, but if it is not good for hand coding, and the GUI builder that uses it behind the scenes does some strange things as everybody says it does, then what is GroupLayout good for?
And since mikael mentioned his creation, I would also take the opportunity to plug my own PageLayout layout manager, which requires you to specify minimal information about your layout , and does everything that you would want to do without prompting you to pull your hair out.
Posted by: varan on December 02, 2006 at 02:12 PM
|