Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Where is better to define the listener in this case ??

0 views
Skip to first unread message

Etantonio

unread,
Jan 12, 2009, 8:13:35 AM1/12/09
to
I'm creating a java gui using swing,
according to my way to divide the problem I create several class, one
for any graphical panel,
So I've a JTabbedPane, in any panel of it I've on the left a different
panel containing a radiobuttongroup, so :

1 JTabbed Pane
a) each tab have a panel on the left with inside a radiobutton group
b) each tab have also a panel with a graph

how I can create an event in a way that when I choose a different
radiobutton I can load a different graph ??,
The problem for me is to retrieve the panel containing a) and b)
starting from inside of a) ,
where is better to define the listener ??

Thanks

Antonio
www.etantonio.it/en


Roedy Green

unread,
Jan 12, 2009, 7:36:07 PM1/12/09
to
On Mon, 12 Jan 2009 05:13:35 -0800 (PST), Etantonio
<etan...@gmail.com> wrote, quoted or indirectly quoted someone who
said :

>The problem for me is to retrieve the panel containing a) and b)
>starting from inside of a) ,
>where is better to define the listener ??

I think you should define your listener nearby where you define
instantiate the component (not necessarily the exact same method -- I
put mine often in "hookListeners). That is where other programmers
will go looking for it.

If the listener code is common, have those listeners call the common
code.

Otherwise programmers will have a heck of a time noticing/finding
listeners. It is difficult enough to pull together all the code you
need to understand a single component.
--
Roedy Green Canadian Mind Products
http://mindprod.com
PM Steven Harper is fixated on the costs of implementing Kyoto, estimated as high as 1% of GDP.
However, he refuses to consider the costs of not implementing Kyoto which the
famous economist Nicholas Stern estimated at 5 to 20% of GDP

Etantonio

unread,
Jan 13, 2009, 7:53:08 AM1/13/09
to

Yes but the listener have to change the graph showed on the other
panel in b)
how I can retrieve that panel ??

Thanks, Antonio

John B. Matthews

unread,
Jan 13, 2009, 9:29:44 AM1/13/09
to
In article
<138abbd6-6da8-4994...@q30g2000prq.googlegroups.com>,
Etantonio <etan...@gmail.com> wrote:

> Yes, but the listener have to change the graph showed on the other
> panel. [H]ow I can retrieve that panel?

Well, you can maintain a global record of tab panels, mapping control
panels to the corresponding view. Instead, just keep them together in
the first place:

<sscce>

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

/** @author John B. Matthews */
public class JTabbedTest {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
(new JTabbedTest()).create();
}
});
}

private void create() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("One", new TabPane());
tabbedPane.addTab("Two", new TabPane());
tabbedPane.addTab("Three", new TabPane());

JFrame f = new JFrame("JTabbedPaneTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(tabbedPane);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class TabPane extends JPanel {

private static final Random random = new Random();
private JPanel control = new JPanel();
private JPanel view = new JPanel();

public TabPane() {
this.setLayout(new BorderLayout());
this.add(view, BorderLayout.CENTER);
this.add(control, BorderLayout.WEST);
view.setPreferredSize(new Dimension(100, 100));
view.setBackground(new Color(random.nextInt()));
JButton change = new JButton("Change");
control.add(change);
change.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
view.setBackground(new Color(random.nextInt()));
}
});
}
}
</sscce>

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>

RedGrittyBrick

unread,
Jan 13, 2009, 9:57:49 AM1/13/09
to

Etantonio wrote:
> Yes but the listener have to change the graph showed on the other
> panel in b)
> how I can retrieve that panel ??

This sounds the wrong way round to me. Shouldn't the objects that needs
to show the change (or make the change) be made observers-of or
listeners-to the observed or listened-to objects. This usually reduces
coupling between classes.

I'd try to follow an MVC pattern.

As you know, it would probably help if you would construct a small
example that illustrates your question (see http://sscce.org.)

--
RGB

Roedy Green

unread,
Jan 13, 2009, 4:55:13 PM1/13/09
to
On Tue, 13 Jan 2009 04:53:08 -0800 (PST), Etantonio

<etan...@gmail.com> wrote, quoted or indirectly quoted someone who
said :

>Yes but the listener have to change the graph showed on the other


>panel in b)
>how I can retrieve that panel ??

You can pass the panel to the common listener handling code as a
parameter.

You can pass the panel to the listener constructor.

Inner anonymous class can have look around at stack and class and
static variables.
see http://mindprod.com/jgloss/anonymousclasses.html

Etantonio

unread,
Jan 13, 2009, 5:03:02 PM1/13/09
to
Thanks, here is how I arranged my code, a different class for any
different portion of the GUI,
maybe it is not a good design pattern, but I like the order in my
code, yes this is just my second GUI,
so I've all to learn. This code dorsn't compile due to the fact that I
don't know how to access the View istance.
Thanks

Antonio
www.etantonio.it/de/


package it.imt.edusat.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;


/** @author A.D'Ottavio featuring John B. Matthews */
public class JTabbedTest {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
(new JTabbedTest()).create();
}
});
}

private void create() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("One", new TabPane());
tabbedPane.addTab("Two", new TabPane());
tabbedPane.addTab("Three", new TabPane());

JFrame f = new JFrame("JTabbedPaneTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(tabbedPane);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class TabPane extends JPanel {
public TabPane() {
this.setLayout(new BorderLayout());
this.add(new View(), BorderLayout.CENTER);
this.add(new Control(), BorderLayout.WEST);
}
}

class Control extends JPanel {

private static final Random random = new Random();

public Control() {


JButton change = new JButton("Change");

add(change);
change.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {

view.setBackground(new Color(random.nextInt())); /
********HERE NOT COMPILE ********************************************
}
});
}
}

class View extends JPanel {

private static final Random random = new Random();

public View() {


JPanel view = new JPanel();

RedGrittyBrick

unread,
Jan 13, 2009, 5:48:31 PM1/13/09
to

Etantonio wrote:
> Thanks, here is how I arranged my code, a different class for any
> different portion of the GUI,
> maybe it is not a good design pattern, but I like the order in my
> code, yes this is just my second GUI,
> so I've all to learn. This code dorsn't compile due to the fact that I
> don't know how to access the View istance.
> Thanks
>

Here's one suggestion ...

Replace the above with

View view = new View();
add(view, BorderLayout.CENTER);
add(new Control(view), BorderLayout.WEST);

Alternatively add a method addListener(ActionListener) to View.


> }
> }
>
> class Control extends JPanel {
>
> private static final Random random = new Random();
>
> public Control() {

public Control(ActionListener listener) {

> JButton change = new JButton("Change");
> add(change);
> change.addActionListener(new ActionListener(){
> public void actionPerformed(ActionEvent e) {
> view.setBackground(new Color(random.nextInt())); /
> ********HERE NOT COMPILE ********************************************
> }
> });

change.addActionListener(listener);

> }
> }
>
> class View extends JPanel {

class View extends JPanel implements ActionListener {

>
> private static final Random random = new Random();
>
> public View() {
> JPanel view = new JPanel();
> view.setPreferredSize(new Dimension(100, 100));
> view.setBackground(new Color(random.nextInt()));
> }

That is plain wrong! View *is-a* JPanel, don't make it *has-a* JPanel
too. Don't mix inheritance and composition of the same class. Pick one.
public View() {
super();
setPreferredSize(new Dimension(100, 100));
setBackground(new Color(random.nextInt()));
}

then add
public void ActionPerformed(ActionEvent e) {
setBackground(new Color(random.nextInt());
}

> }

You could leave everything as it was and pass view as a View or JPanel
parameter to Control's constructor or to an addView()/AddJPanel() method
but this would couple the classes too tightly.

Using ActionListener this way is a bit questionable. It would probably
be better to use the Observer pattern so that changes to the view can
also be triggered by other types of event, not just ActionEvents.

--
RGB

Etantonio

unread,
Jan 13, 2009, 6:39:59 PM1/13/09
to
SO finally the code you suggest seems to be the following :
I'm an old programmer, I don't like very much to pass all a JPanel
like View as an argument to the constructor of Control,
it is just a reference, I know, but I always think to class like huge
objects, and think that this could bring to slow java programs,
but I'm sure that if you suggest this to me this is not true.
The code pass for the actionPerformed method but no color change (this
is another problem :-) ) .

Do someone can display to me the observer pattern for this example ??

Thanks anyway and again

Antonio
www.etantonio.it/en

package it.imt.edusat.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public class JTabbedTest {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
(new JTabbedTest()).create();
}
});
}

private void create() {
JTabbedPane telemetryGroupsTabs = new JTabbedPane();
telemetryGroupsTabs.addTab("One", new TelemetryGroup());
telemetryGroupsTabs.addTab("Two", new TelemetryGroup());
telemetryGroupsTabs.addTab("Three", new TelemetryGroup());

JFrame f = new JFrame("JTabbedPaneTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.add(telemetryGroupsTabs);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class TelemetryGroup extends JPanel {
public TelemetryGroup() {
this.setLayout(new BorderLayout());


View view = new View();

this.add(new View(), BorderLayout.CENTER);
this.add(new Control(view), BorderLayout.WEST);
}
}

class Control extends JPanel {

private static final Random random = new Random();

public Control(ActionListener listener) {


JButton change = new JButton("Change");
add(change);

change.addActionListener(listener);
}

}

class View extends JPanel implements ActionListener {

private static final Random random = new Random();

public View() {


setPreferredSize(new Dimension(100, 100));
setBackground(new Color(random.nextInt()));
}

public void actionPerformed(ActionEvent e) {
setBackground(new Color(random.nextInt()));
repaint();
}
}

Etantonio

unread,
Jan 13, 2009, 7:32:05 PM1/13/09
to
to implement the observer pattern using java.util.observer probably I
need to do something like this :

class Control extends Observable, JPanel { ... }


class Control extends Observer, JPanel { ... }

but naturally it is not possible to extend from 2 different classes

Lew

unread,
Jan 13, 2009, 7:57:27 PM1/13/09
to
Etantonio wrote:
> to implement the observer pattern using java.util.observer

You aren't going to get very far spelling the interface name wrong like that.
<http://java.sun.com/javase/6/docs/api/java/util/Observer.html>

> probably I need to do something like this :
>
> class Control extends Observable, JPanel { ... }
>
>
> class Control extends Observer, JPanel { ... }
>
> but naturally it is not possible to extend from 2 different classes

It's not even possible to extend Observer, since it's an interface and one
doesn't extend interfaces.

It is possible to extend Observable and implement Observer in the same class,
but that doesn't make a whole lot of sense to me.

It is possible to use the observer pattern without using either.
<http://www.ibm.com/developerworks/java/library/j-jtp07265/index.html>
for example.

--
Lew

Etantonio

unread,
Jan 13, 2009, 8:19:07 PM1/13/09
to
You are right, the preceding message of mine was written without very
much mind,
but was 1:30am here in Rome and I was thinking to go to sleep, now are
about 2:15 and the problem is still not completely solved,
you're right, Observer is an interface, true problem at the moment is
that Observable is a class and not an interface so I couldn't do the
following :


class View extends JPanel extends Observable {

but I need that View extend JPanel because it contains my graph and
RadioButtonGroup

Thanks,

Antonio

John B. Matthews

unread,
Jan 13, 2009, 8:49:34 PM1/13/09
to
In article
<f112c2ad-4c47-4a65...@v13g2000yqm.googlegroups.com>,
Etantonio <etan...@gmail.com> wrote:

Typically, you would have a model that extends Observable and notifies
listeners, perhaps periodically or when a value changes. The view would
implement Observer to respond to the model's notification.

In your design, the model would acquire values for temperature, voltage
and current from an external interface. Each registered observer's
update() method would be invoked when the model calls
notifyObservers().

<http://java.sun.com/javase/6/docs/api/java/util/Observer.html>
<http://java.sun.com/javase/6/docs/api/java/util/Observable.html>
<http://en.wikipedia.org/wiki/Observer_pattern>

Lew

unread,
Jan 13, 2009, 10:46:15 PM1/13/09
to
Etantonio wrote:
> You are right, the preceding message of mine was written without very
> much mind,
> but was 1:30am here in Rome and I was thinking to go to sleep, now are
> about 2:15 and the problem is still not completely solved,
> you're right, Observer is an interface, true problem at the moment is
> that Observable is a class and not an interface so I couldn't do the
> following :
>
> class View extends JPanel extends Observable {

Thank goodness you can't do that!

> but I need that View extend JPanel because it contains my graph and
> RadioButtonGroup

Swing already supports the observer pattern via its events (observables) and
event listeners (observers), as specifically mentioned in the link I provided
upthread:
> The Swing framework makes extensive use of the Observer pattern
> (also known as the publish-subscribe pattern) in the form of
> event listeners. Swing components that are the targets of user
> interaction fire events when the user interacts with them; data
> model classes fire events when the data has changed. The use of
> Observer in this way lets the controller be separated from the
> model, and the model be separated from the view, simplifying
> the development of GUI applications.

There is not any need to use the specific class 'Observable'.

Even if you did, you could do it through composition rather than inheritance,
usually preferable: include an 'Observable' member in your JPanel rather than
extending it, and/or include a 'JPanel' rather than extending it.

(See /Effective Java/, by Joshua Bloch,
<http://java.sun.com/docs/books/effective/index.html>,
"Item 16: Favor composition over inheritance".)

You have to decide whether the subtype should be a view (extend JPanel) or a
model (extend a non-visual logic class embodying your domain). Or, perhaps, a
controller (extend neither one but coordinate actions between them).

Think about what exactly you want observed. If it's GUI events, Swing classes
can already do that. If it isn't, then you most certainly do not want a GUI
class to be the observable.

--
Lew

RedGrittyBrick

unread,
Jan 14, 2009, 5:05:38 AM1/14/09
to

Etantonio wrote:
> SO finally the code you suggest seems to be the following :
> I'm an old programmer, I don't like very much to pass all a JPanel
> like View as an argument to the constructor of Control,
> it is just a reference, I know, but I always think to class like huge
> objects, and think that this could bring to slow java programs,

Firstly, as you say, all that is being passed is a reference to an
object. The reference is probably the same size for a tiny object as for
an enormous object. It is just a pointer. Size of object should have no
effect on speed in this area and even if it did, you'd probably have to
be making millions of such constructor or method calls to notice any
effect on responsiveness of the application. Most Java programmers
rightly value correctness and maintainability above performance.

Secondly, you are actually passing a reference that points not to a View
but to an ActionListener - that is what is defined by the "signature" of
the constructor or method.

> but I'm sure that if you suggest this to me this is not true.

Quite!

> The code pass for the actionPerformed method but no color change (this
> is another problem :-) ) .
>

My guess is you didn't correct the definition of View which both
extended JPanel and encapsulated one.

Tested working code:
-----------------------------------8<-----------------------------------
package it.imt.edusat.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

/** @author A.D'Ottavio featuring John B. Matthews */

public class JTabbedTest {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
(new JTabbedTest()).create();
}
});
}

private void create() {


JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("One", new TabPane());
tabbedPane.addTab("Two", new TabPane());
tabbedPane.addTab("Three", new TabPane());

JFrame f = new JFrame("JTabbedPaneTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(tabbedPane);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class TabPane extends JPanel {
public TabPane() {

this.setLayout(new BorderLayout());
View view = new View();

this.add(view, BorderLayout.CENTER);
this.add(new Control(view), BorderLayout.WEST);
}
}

class Control extends JPanel {

private static final Random random = new Random();

public Control(ActionListener listener) {
JButton change = new JButton("Change");
add(change);
change.addActionListener(listener);
}
}

class View extends JPanel implements ActionListener {

private static final Random random = new Random();

public View() {
setPreferredSize(new Dimension(100, 100));
setBackground(new Color(random.nextInt()));
}

public void actionPerformed(ActionEvent e) {
setBackground(new Color(random.nextInt()));
}
}

-----------------------------------8<-----------------------------------

RedGrittyBrick

unread,
Jan 14, 2009, 5:14:18 AM1/14/09
to

Lew addressed this.

Another approach to consider is define a javax.swing.Action member for
View and pass it to Control.

e.g.
new Control(view.getAction());

or
Control control = new Control();
control.setAction(view.getAction());

or
Control control = new Control();
control.setButtonAction(view.getAction());

according to taste.


See http://java.sun.com/javase/6/docs/api/javax/swing/Action.html

--
RGB

Etantonio

unread,
Jan 14, 2009, 10:18:41 AM1/14/09
to
Ok, this evening I'll try to implement the Action approach and let you
know the results.
Thanks

Antonio
www.etantonio.it/Forums/Varie

0 new messages