CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    How to send an event to child's parent class

    I am very much a beginner in Java. In my application I would like the child class to send an event to the parent class (both are JPanel classes). I looked in a number of books, checked the java tutorials at Sun and have not found an example. Is it possible?

    Mike



  2. #2
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: How to send an event to child's parent class

    Yes, it is possible, but it could be a lot of hard code for a beginner. Perhaps there would be a simpler way if you would be more specific in your question. Like what object has what type of event you want to pass.
    One way would be to use the addListenerXXX interface. Add an addXXXListener(XXXListener) method to the child class and have it save the reference to the XXXListener. Create a XXXListener interface with a method such as xxxHappended(). Have the parent class implement the XXXListener interface and call the child's addXXXListener(this); Then when the child has an XXX event, it can call all the listeners' xxxHappenened() method with an XXXEvent object.
    I don't think a beginner really wants to do all this.


    Norm
    Norm

  3. #3
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    Re: How to send an event to child's parent class

    Norm,

    Thanks for the quick reply. Only a beginner in JAVA, not a beginner in programming.

    In the JAVA docs I did notice the many mouse and item listeners, and there are some in my code as well.

    I'll be more specific. My parent class has two child classes. One child class has sliders used in creating a set of data. The other child class is to display the data. The two child classes don't know about each other. I would like the display child class to update its display when the slider child class has created new data. I thought sending an event to the parent class would be the best approach to this. Make sense?

    Which addXXXListener interface do I use?

    Mike


  4. #4
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to send an event to child's parent class

    Sliders don't themselves create data, they just select values. If these values are the data you want to pass to the data display panel, then make the data display panel implement the ChangeListener interface and add itself to the sliders using addChangeListener() (or have it create an anonymous change listener and pass it to the sliders using addChangeListener()).

    This way the display panel will get notified when the slider values change.

    If the slider values are not the data you had in mind, perhaps you could explain a bit more about how these data are created from the slider values...

    Dave

    Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  5. #5
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: How to send an event to child's parent class

    You could have the display class be a listener to the slider class. The display class would implement a XXXListener interface. When an XXX event takes place in the Slider, it calls its listener(Display) to report it:

    // in parent class
    Slider s = new Slider(); // generates XXX events
    add(s);
    Display d = new Display(); // implements XXXListener
    add(d);
    s.addXXXListener(d); // Slider to notify Display when XXX event




    Norm
    Norm

  6. #6
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    Re: How to send an event to child's parent class

    Dave,

    The value of the sliders are used in the computation of data that gets placed into a Vector based class.
    I want to avoid interaction between the slider class and display class as that will make one dependent on the other. Can't have that.

    Mike


  7. #7
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    Re: How to send an event to child's parent class

    Thanks again for responding.

    I think I need to explain further what I am doing.

    I have a JPanel(parent) class. It is a parent to another JPanel(sliders) class which has 12 sliders (and has a data class that extends Vector). The parent JPanel is also a parent to another JPanel(display) class. The display class is passed the vector class by the parent:

    parent.displayClass.SetData(parent.sliderClass.GetData());

    Each time one of the sliders change in the slider class, new XYZ data is generated in response to the the Vector class.

    When new data is generated (because a slider changed) I would like the display class to redraw the data. Currently I'm doing it by responding to a button click in the display class panel.

    I don't see how adding the display class as a Listener to the slider class would work. Is addXXXListener a new class that I need to create?

    Hopefully I provided enough details.
    Mike


  8. #8
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to send an event to child's parent class

    OK, that sounds sensible. In that case, you need a calculator object that listens to the sliders, performs the calculations, and is, in turn, listened to by the display class.

    It's not such a big deal to make a listenable object, you just give it an EventListenerList, methods to add and remove listeners, and methods to fire events. The JavaDoc for EventListenerList shows examples. You can reuse ChangeListener and ChangeEvent for the calculator class, perhaps something like thisublic class MyCalculator implements ChangeListener {
    // Hold listeners here
    EventListenerList listenerList = new EventListenerList();

    ChangeEvent changeEvent = null; // To be sent to listeners
    private Data data = null; // Data to be calculated

    public Data getData() {
    return data;
    }

    // Handle slider value changes and fire data change event to display
    public void stateChanged(ChangeEvent e) {
    JSlider source = (JSlider)e.getSource();
    if (!source.getValueIsAdjusting()) {
    int value = (int)source.getValue();
    data = new Data(value); // calculate the data from the value
    fireChangeEvent(); // notify listeners of change
    }
    }

    public void addChangeListener(ChangeListener l) {
    listenerList.add(ChangeListener.class, l);
    }

    public void removeChangeListener(ChangeListener l) {
    listenerList.remove(ChangeListener.class, l);
    }

    protected void fireChangeEvent() {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[ i ]==ChangeListener.class) {
    if (changeEvent == null)
    changeEvent = new ChangeEvent(this);
    ((ChangeListener)listeners[ i+1 ]).stateChanged(changeEvent);
    }
    }
    }

    public class DataDisplay implements ChangeListener {
    public void stateChanged(ChangeEvent event) {
    MyCalculator mc = (MyCalculator)event.getSource();
    display(mc.getData());
    }
    }

    // somewhere in your application:
    ...
    DataDisplay display = new DataDisplay(...);
    MyCalculator calculator = new MyCalculator();
    calc.addChangeListener(display);
    slider.addChangeListener(calculator);
    ...


    Note: this is uncompiled, untested code.

    It may look a bit complicated for such a simple requirement, but it can cater for any number of listeners without close coupling between them. In this kind of situation, I might be inclined to abstract the ChangeListener implementation code into a superclass that MyCalculator (and other classes that might need it) could extend. Alternatively, for a more OO solution, see the way it's done in the JSlider.java code.

    Dave

    Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  9. #9
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    Re: How to send an event to child's parent class

    Dave,

    Excellent! Thanks much for the contribution to my skill set. I'll look this over and see how I can put it to use in my code. This is my first Java application.

    Mike



  10. #10
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,877

    Re: How to send an event to child's parent class

    My idea was the slider class is a source of an event (DataChanged) that the display class wants to know about. So you have the display class register itself with the slider class as a Listener for DataChanges. When there is a DataChnage event (slider moved) the slider class calls its listener with a DataChangedEvent telling the display class about the change.
    Here's some code from a textbook I have showing how to create your own custom event. One of the things about it that's important is that the callback to the listener is done on a separate AWT-engine thread instead of your event source's thread.
    /* Create a CustomEvent: TimerEvent and use it to control the drawing
    of a horizontal bar in a small frame.

    * Cay S. Horstmann & Gary Cornell, Core Java
    * Published By Sun Microsystems Press/Prentice-Hall
    * Copyright (C) 1997 Sun Microsystems Inc.
    * All Rights Reserved.
    *
    * Permission to use, copy, modify, and distribute this
    * software and its documentation for NON-COMMERCIAL purposes
    * and without fee is hereby granted provided that this
    * copyright notice appears in all copies.
    *
    * Minor modifications by Norm Radder
    */

    /**
    * @version 1.10 25 Mar 1997
    * @author Cay Horstmann
    */

    import java.awt.*;
    import java.awt.event.*;
    import java.util.Date;

    public class CustomEventTest extends Frame implements TimerListener{
    private int ticks = 0; // Count number of timeElapsed

    // Constructor
    public CustomEventTest() {
    Timer t = new Timer(1000); // Call me in 1 sec
    t.addTimerListener(this);

    setTitle("CustomEvent test");
    addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
    System.exit(0);
    }
    });
    setLocation(200, 200);
    setSize(100, 50);
    } // end Constructor

    // Here is the callback routine for the Timer
    // It draws a lengthening line left to right
    public void timeElapsed(TimerEvent evt) {
    Graphics g = getGraphics();
    g.translate(getInsets().left, getInsets().top);
    g.drawRect(0, 0, ticks, 10);
    ticks++;
    }

    // Start the test
    public static void main(String[] args) {
    CustomEventTest f = new CustomEventTest();
    f.show();
    }

    } // end class CustomEventTest

    // ------------------------------------------------------------------------
    // Following are interface and classes to define the Timer:

    // Define the TimerListener Interface
    interface TimerListener {
    // Call this routine when time elapses
    public void timeElapsed(TimerEvent evt);
    }

    //------------------------------------------------------------
    // Define the Timer class
    // Only room for 1 listener
    // Continually creates TimerEvents every interval
    class Timer extends Component implements Runnable {
    private int interval;
    private TimerListener listener; // NB only 1 listener allowed
    private static EventQueue evtq;

    // Constructor
    public Timer(int period) {
    interval = period;
    Thread t = new Thread(this);
    t.start();
    evtq = Toolkit.getDefaultToolkit().getSystemEventQueue();
    enableEvents(0); // Enable events to come here
    }

    // Add the TimerListener (only room for one)
    public void addTimerListener(TimerListener l) {
    listener = l;
    }

    // Forever loop to return a event every interval
    public void run() {
    while (true){
    try { Thread.sleep(interval); }
    catch(InterruptedException e) {} // Ignore
    TimerEvent te = new TimerEvent(this);
    System.out.println("Before post of " + te + " on " + Thread.currentThread());
    evtq.postEvent(te); // Post new event to be processed below
    System.out.println("After post of " + te+ " on " + Thread.currentThread());
    }
    }

    // Check for and process our TimerEvent
    // This method is called when the event is removed from the queue
    // It runs on a thread from the queue processor
    public void processEvent(AWTEvent evt) {
    if (evt instanceof TimerEvent) {
    if (listener != null) {
    System.out.println("Processing of " + evt + " on " + Thread.currentThread());
    //Call the callback routine
    listener.timeElapsed((TimerEvent)evt);
    }
    }else {
    // If not ours, pass it on
    super.processEvent(evt);
    }
    }

    } // end class Timer

    //--------------------------------------------------------------
    // Define the TimerEvent and give it a unique id (hopefully)
    class TimerEvent extends AWTEvent {
    public static final int TIMER_EVENT = AWTEvent.RESERVED_ID_MAX + 5555;
    long time;

    public TimerEvent(Timer t) {
    super(t, TIMER_EVENT);
    time = System.currentTimeMillis();
    }
    // Show something for debugging output
    public String toString() {
    return "TimerEvent at " + time;
    }
    } // end class TimerEvent
    /* Output:
    Running: java CustomEventTest

    Before post of TimerEvent at 1006006144980 on Thread[Thread-1,5,main]
    Processing of TimerEvent at 1006006144980 on Thread[AWT-EventQueue-0,6,main]
    After post of TimerEvent at 1006006144980 on Thread[Thread-1,5,main]
    Before post of TimerEvent at 1006006146030 on Thread[Thread-1,5,main]
    Processing of TimerEvent at 1006006146030 on Thread[AWT-EventQueue-0,6,main]
    After post of TimerEvent at 1006006146030 on Thread[Thread-1,5,main]
    Before post of TimerEvent at 1006006147020 on Thread[Thread-1,5,main]
    Processing of TimerEvent at 1006006147020 on Thread[AWT-EventQueue-0,6,main]
    After post of TimerEvent at 1006006147020 on Thread[Thread-1,5,main]

    0 error(s)
    */



    Norm
    Norm

  11. #11
    Join Date
    Nov 2001
    Location
    California
    Posts
    7

    Re: How to send an event to child's parent class

    Norm,

    Thanks for the extensive help. I have my code working the way I want now. Thanks much.

    Mike



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured