Event handling

Hi,

I am actually not sure if this is the right place for my question but I probably will notice if not.
I come from an ActionScript background and am now dealing with Java to which I would like to port some graphical stuff I have made in “Flash” before.
The rendering is no problem for me at all but which makes me some headache is the way events are handled in Java because I have some swing gui that interacts with my model.

For instance given a custom GUI component (which extends JPanel) is composed of two other GUI components:JLabel and JButton.
If the user clicks on the JButton instance I would like to now the state of the JLabel (from a parent component which instanciated my custom component) without nowing much about the custom component (loose coupling).

So imho it would be the best solution to forward the new state(in this case it is the String of the label) as part of the custom event.

In ActionScript I couldy easily dispatch an custom event like this:


class MyCustomComponent extends Sprite {
  private const myButton : MyButton = new Button();

  public function MyCustomComponent() {
    myButton.addEventListener(MouseEvent.CLICK, onButtonClick);
  }

  private function onButtonClick(event : MouseEvent) : void {
    dispatchEvent(new CustomEvent("change", "new string"));
  }
}

Another GUI component could handle events of MyComponent like this:


var myCustomComponent : MyCustomComponent = new MyCustomComponent();
myCustomComponent.addEventListener("change", onCustomComponentChange);

In onCustomComponentChange I then could handle the changed state of the component.

So how is this solved “correctly” in Java?

Unfortunately it seems that I can not dispatch custom events that forward objects to the listener.
I thought about some objective c delegate solution:


myCustomComponent.delegate = myDelegate;

where the delegate needs to implement some component specific callbacks.
But this smells boilerplate.

Maybe I have missed something fundamental?

Thank you for your time, any help is appreciated :slight_smile:

My mind is currently somewhere else but seems You’d like something like this ?


class MyComp implements SomeListener
{
	JLabel label = new JLabel("With text");
	JButton button = new JButton("Press me");
    
	/* some init method, constructor or whathave You */
	void init()
	{
		button.addListener(this);
	}

	// This from the action listener
	void someActionPerformed(SomeActionEvent e)
	{
		if ( e.getObject() == button ) 
		{
			//At this point You have access to the button and to the label
			System.out.println(label.getText());
		}
	}
}

Note: this is more like a pseudo code than a real code, but the idea is valid.
There should be some tutorial around, that show the basic swing event handling.

Check, what “add*Listener” methods are available for the components You use. Then just implement the appropriate listener and use the events provided to the listener methods.

If you need custom events, and not built-in events as xsvenson speaks of, there are two available options. You can choose which one is more appropriate for your situation.

  1. Use java.beans.PropertyChangeEvents. JComponents can fire such events by any of their many firePropertyChange() overloads. Then the other component interested in these events would call customComponent.addPropertyChangeListener(“propName”, this); This technique is common if you have say boolean, int or String properties that other components might be interested in receiving change notifications for.

  2. The second option is more legwork, but allows you to notify listeners with an entire event object containing arbitrary data, instead of just an old/new value pair. Roll your own Event class (subclassing java.util.EventObject), Listener interface (extending java.util.EventListener), and make your custom component accept Listeners of that type. It follows the same pattern as the “built-in” event types like ActionListener, so it’s pretty straightforward. A simple example can be found here. Note that JComponents already have a protected EventListenerList field named “listenerList”, so you don’t have to add such a field in your custom component yourself.

Thank you very much BoBear2681,
so basicly I need to implement the Observer Pattern by myself given the interface provided by Java.
While this is exactly what I have been looking for, I wonder why(if) there isn’t any implementation but only the private field :/.
However, this helped me a lot :slight_smile: