Prev: Noted Speakers, Workshops and lots more at Sun Tech Days 2010 Conference
Next: Is this GC.log summary indicating memory leak ?
From: Fencer on 17 Feb 2010 10:03 Hello, in my program I toggle between two panels depending on which phase the program is currently in. I wrote a class that functions as the entry point of the program and it's composed of a JFrame along with the components of that frame. Now I wanted to break out my two panels to make the code more readable so I created two new classes that extend from JPanel and here's where my design issue arose. Consider the code below (people who have been following my other thread will recognise it ;-)) which is for the "welcome panel" that is shown when the program is launched: package gui; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.border.TitledBorder; public class WelcomePanel extends JPanel { private static final long serialVersionUID = 1596841645688614873L; public WelcomePanel(final CenteredGroup inst) { this.inst = inst; setPreferredSize(new Dimension(480, 100)); setBorder(new TitledBorder("Start a new session by opening a BioModel or load a previously saved session")); setLayout(new GridBagLayout()); initButtons(); } private void initButtons() { final CenteredGroup inst2 = this.inst; b1 = new JButton("Open BioModel"); b1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { inst2.eventOpenBioModel(); }}); b2 = new JButton("Load Saved Session"); b2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { inst2.eventLoadSavedSession(); }}); addButtonsToGroupPanel(b1, b2); } private void addButtonsToGroupPanel(JButton b1, JButton b2) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.weightx = 0.5; gbc.weighty = 0; gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; add(b1, gbc); gbc.gridx = 1; add(b2, gbc); } private CenteredGroup inst = null; private JButton b1 = null; private JButton b2 = null; } What I don't like here are the event handlers for the buttons and, more specifically, I don't like these two things: 1. The class WelcomePanel knows about its "parent", CenteredGroup (I will change that name btw). 2. I had to change the event*-methods in CenteredGroup from being private to default access level so I could call them. Am I right to worry about these design issues and, if so, how should I solve them? Maybe I shouldn't have created this class in the first place but I thought the code for CenteredGroup was becoming a bit long. Thanks for reading and thanks in advance for any help. - F
From: markspace on 17 Feb 2010 10:21 Fencer wrote: > 1. The class WelcomePanel knows about its "parent", CenteredGroup (I > will change that name btw). Normally, this is not an issue. Your code does appear a bit odd however, though I haven't pinned down why. > 2. I had to change the event*-methods in CenteredGroup from being > private to default access level so I could call them. Not a problem at all. Normally, you code to interfaces, which are nearly always public. Thus CenteredGroup should implement some interface, which other classes can code too. WelcomePanel can use that public interface to call CenteredGroup's methods. I think what's weird about your code is the lack of MVC. The code seems all sort of muddled together to me. Take a look at your problem, break it into MVC, and add interfaces for the views and the model (since this is just welcome screen, you may have very little "model" in your code). Then see if you can explain it in a higher level context.
From: Fencer on 17 Feb 2010 10:47 On 2010-02-17 16:21, markspace wrote: > Fencer wrote: > >> 1. The class WelcomePanel knows about its "parent", CenteredGroup (I >> will change that name btw). > > > Normally, this is not an issue. Your code does appear a bit odd however, > though I haven't pinned down why. > > >> 2. I had to change the event*-methods in CenteredGroup from being >> private to default access level so I could call them. > > > Not a problem at all. Normally, you code to interfaces, which are nearly > always public. > > Thus CenteredGroup should implement some interface, which other classes > can code too. WelcomePanel can use that public interface to call > CenteredGroup's methods. > > I think what's weird about your code is the lack of MVC. The code seems > all sort of muddled together to me. Take a look at your problem, break > it into MVC, and add interfaces for the views and the model (since this > is just welcome screen, you may have very little "model" in your code). > Then see if you can explain it in a higher level context. Thanks for your reply. MVC, hmm. Ok, so imagine WelcomePanel is a view and instead of knowing about the CenteredGroup class directly it knows about an interface for a Controller. When the user presses the button "Open BioModel" the view informs the controller about this. What should happen now is that a file selection dialog should appear where the user can select a biomodel file which is then processed. But who should display this file selection dialog? Maybe WelcomePanel should do that and then inform the controller that this event has occurred and this biomodel file was choosen and the controller would then proceed from there? As you can see I have trouble deciding what goes where, heh. :-) - Fencer
From: Lew on 17 Feb 2010 11:41 Fencer wrote: > MVC, hmm. Ok, so imagine WelcomePanel is a view and instead of knowing > about the CenteredGroup class directly it knows about an interface for a Controller. Normally you'd do it the other way around - the controller knows about the view, but the view doesn't know about the controller. > When the user presses the button "Open BioModel" the view > informs the controller about this. What should happen now is that a file This is where the controller knows the view. The central view method returns a value, and takes arguments, that the controller understands. The view types know nothing about how the arguments are created or the return values are used. > selection dialog should appear where the user can select a biomodel file > which is then processed. But who should display this file selection dialog? The view under the direction of the controller. > Maybe WelcomePanel should do that and then inform the controller that Calling it a welcome "panel" already locks down implementation too far. The fact that it's a panel is almost certainly irrelevant to the controller. > this event has occurred and this biomodel file was choosen and the > controller would then proceed from there? The controller knows when to ask for the "Welcome Interaction" (or "Screen" or whatever application-domain concept you use), what to pass to it, and what to do with the result, i.e., to where to navigate based on the return value and what data to pass to the model or behaviors to invoke on it. References (be sure to follow links from these as well): <http://en.wikipedia.org/wiki/Model_2> <http://en.wikipedia.org/wiki/Model-View-Controller> <http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html> <http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html> -- Lew
From: Fencer on 17 Feb 2010 12:15
On 2010-02-17 17:41, Lew wrote: > Fencer wrote: >> MVC, hmm. Ok, so imagine WelcomePanel is a view and instead of knowing >> about the CenteredGroup class directly it knows about an interface for >> a Controller. > > Normally you'd do it the other way around - the controller knows about > the view, but the view doesn't know about the controller. > >> When the user presses the button "Open BioModel" the view informs the >> controller about this. What should happen now is that a file > > This is where the controller knows the view. The central view method > returns a value, and takes arguments, that the controller understands. > The view types know nothing about how the arguments are created or the > return values are used. Thanks for your reply. I will read some more and try to make a concept implementation. Just one question, if the view (a JPanel in my case) doesn't know about the controller but the controller knows about the view, how should I implement my button listener? Right now it's an anonymous inner class to the JPanel-extended class, I don't get how to handle that and not have the view know the controller? [snip] - F |