This week's book giveaway is in the OCMJEA forum. We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line! See this thread for details.
Having looked at a lot of code, I've found considerable variability in how things are done, especially putting GUI elements together. Here is a really simple case, but meant to represent the case where panel1 and panel2 actually have a lot of elements in them.
I have the option of putting all the commands in one constructor to build the whole thing, breaking the code up into methods to build the pieces, making multiple inner classes that construct the pieces or having each piece in their own class. I've implemented each possibility. Is any one of these 'best practice?' Or if depends on the situation, are there tips on when to use each of these constructs? I'm not real happy with the last case (separate classes) since the action listener is in one class and the panel is built in another. Did I extract out the panel correctly?
I think I am pretty close to forming a habit for how I do this, so I thought I'd ask the opinions of others before getting entrenched in a bad habit. It would help if there is some good reason to favor or disfavor any of these approaches if I knew the reason.
The simplest thing to do is build all the elements in one class.
However, in practice this can make classes with lots of lines of code in them. I've heard some rule of thumb that if the code won't fit on the screen, trying pulling some of it out into functions, which I can do as methods in Java.
If I had a lot of code involved in making panel1 or panel2, that would at least make GUITest1 more readable. But I could also implement this with classes, which seems more 'Java-like.' Though I have no need to reuse these classes.
OK, so now that I have defined classes, I could move the class definitions to a separate file. I've not usually seen the ActionListener classes moved to their own file. In the above three implementations all the variables are known both to the constructor of the panel and the action listener, so I don't have to pass information around. Once the panel is in it's own class, it will need to let the main panel know who it's buttons are for the action listener. On the other hand, the file sizes become more manageable and I can write routines that just test one class or another. So I may be going to far- but here is a fourth implementation.
Is this last bit right? It seems odd to extract out the bits to make the panel and then have to go to a lot of work to get those bits back so I can set up the action listeners in the main block. Should I have pulled them out as well. In that case, I would appear to need to set an argument as to who the other button is, so they could update what they need to.
i apologize ahead of time for not reading your code. you are right there are several ways to do it. i used to extend JFrame and implement the interfaces. i still do this sometimes, but inner classes are nice. (anonymous or otherwise). they have access to the outer class variables so you don't have to pass "this" to them like you do for separate top level classes. just think twice about if the code is truly tied to the main class and unusable anywhere else. once you get the code working look for places where the code is doing too much(actionPerformed is the most common culprit). make separate methods and call then from actionPerformed.
Disagree about actionPerformed(). I think you should have different classes for the different kinds of actionPerformed(). If you look for my posts in the GUIs forum, you will find I write about that every now and again. But nowadays I usually simply refer to my old posts!
Joined: Oct 10, 2011
Thanks. All my examples have separate classes for each type of action performed. They are inner classes of the main GUI class. That's what you are suggesting, correct?
Really, it doesn't matter all that much, as long as the code is readable.
Personally I pretty always use anonymous classes for all listeners. For timers, I usually add an anonymous ActionListener in-line. For Actions (as in commands like cut, copy, paste, open file, that sort of thing) I usually create an anonymous instance and initialize a field with it.
For panels it depends. Complex panels (like 'canvasses' with animated content) get their own source file. Simple one that only contain a few buttons and maybe text areas just get created in the constructor of their parent frame/panel.
Just try to keep the code concise and readable.
Joined: Oct 13, 2005
Sounds as though all three actually do the same thing. You will sometimes find examples where you may wish to reuse a Listener class, in which case it can be a public top-level class. Example here, but you would wish to change class ColourListener to public class ColourListener, and put it into its own file.
We usually discuss Listeners on the GUIs forum, so I shall move this discussoin thither.
Joined: Oct 10, 2011
Thanks that link was really helpful. I've noticed Java doesn't exactly steer you toward one best way to do things. So at this stage I spend a lot of time head scratching wondering which way to go. As you said, my four examples all do the same thing. I suspect I'll tend to fall into a habit of one approach for most cases and didn't want to be starting off with any major bad habits.
I've also noticed I'm starting to collect a lot of private variable definitions at the top of my class, so that my various action listeners can make use of them. Is that the normal way of things in Java? For example, I have a panel with 5 text fields, two comboboxes, a set of radio buttons and a checkbox. So I have variables declared for are all of them at the start.
I also have a lot of static final strings, as I was asked not to hard-code any labels, they are all declared as constants at the top of the file. Does java have the concept of header files and should I collect those label names there?