Button Events Within Templates

@tarun89engg, Java Swing runs the innermost event. If a parent component has a mousePressed script, but a child inside that parent has a mouseEntered script, any time your mouse is over both the child and the parent, only the child’s mouse events will be run.

That means if you have mouse events on both the parent and child, you need to program the scripts on the child to somehow invoke the scripts on the parent. A straightforward way to do that is by having a mouse event on the child finish by invoking the same mouse event on its parent.


I have a button template where mouse events exist inside the template, but like @Kyle_Chase, I also want to be able to write scripts on template instances (so somebody can place the template and code a script on it in exactly the same way they would with a regular button). For that, I accomplish the same thing he did in the following way:

The five mouse events on the child component have scripts that do whatever the child component needs them to do, but the scripts always finish with this:

template = event.source.parent
template.passEventToInstance(event)

The passEventToInstance() custom method looks like this:

	from javax.swing import SwingUtilities
	
	btn = self.parent
	convertedEvent = SwingUtilities.convertMouseEvent(event.source, event, btn)
	btn.dispatchEvent(convertedEvent)

As the name suggests, SwingUtilities.convertMouseEvent() converts a mouse event on one component into a mouse event on another component (e.g. a mousePressed event on the child component would be converted to a mousePressed event on the parent). SwingUtilities has the added benefit of converting the event coordinates, so the location of the event should still work out correctly if the parent cares about that. The btn.dispatchEvent() function invokes the newly-converted event on that component (i.e. it makes that new mousePressed event on the parent actually “happen”).

4 Likes

@chris3145
Thanks for your clear explanation.
Now the concept is clear to me.

This was super helpful! Note by default, buttons add an action/actionPerformed script rather than one of the five mouse events (i.e. if you use the UI to automatically generate a script to open a popup window). This cannot be passed up to the parent template instance, which does not have action/actionPerformed scripts but only mouse events. Trying anyway causes an error due to type mismatching (java.awt.event.ActionEvent rather than type java.awt.event.MouseEvent).

However, it’s easy enough to move the actionPerformed script into a mouse event script instead, and this got it working for me. Thank you!!!

1 Like

Attempting to extend the above approach to PropertyChange:

To support PropertyChange, the following were added to the imports:

from javax.swing import SwingPropertyChangeSupport

Currently, the firePropertyChange() triggers the following error:

Error:

Caused by: org.python.core.PyException: Traceback (most recent call last):
File "<event:propertyChange>", line 8, in <module>
File "<custom-function passEventToInstance>", line 15, in passEventToInstance
AttributeError: type object 'java.beans.PropertyChangeEvent' has no attribute           'firePropertyChange'

Docs indicate a firePropertyChange(PropertyChangeEvent evt) method:
https://docs.oracle.com/javase/7/docs/api/javax/swing/event/SwingPropertyChangeSupport.html

Code:

Template / Numeric Text Field / propertyChange

if event.propertyName == 'value':
     template = event.source.parent
 template.passEventToInstance(event)                    

Template / Custom Method / passEventToInstance

def passEventToInstance(self, event):
     from java.beans import PropertyChangeEvent

     ntf = self.parent
     convertedEvent = SwingPropertyChangeSupport.firePropertyChange(event.source, event)
     ntf.dispatchEvent(convertedEvent)	

The Goal:

When the Numeric Text Field (within the template instance) value change event occurs, re-trigger the event at the (Template) Instance level to add additional functionality.

Insights?

Previous Post - Excellent!

1 Like