I am looking for a bindable event for the dropdown component on a scripting function.
Current issue is that the GUI method of entry that I am pleased with is having a dropdown component trigger a script that will populate other components from a SQL query.
While I can bind it off a propertyChange script bound to a selectedID/selectedValue, these bindings evaluate immediately and trigger a SQL query with every change. A user that has a dropdown selected and holds down on the keyboard will trigger a great amount of requests.
My current musings on how to tackle the problem are to bind a timer component to the dropdown and only count when the mouse cursor is over the component and then reset back to 0 when the mouse moves off the dropdown, delaying any writes until the timer resets/goes to 0.
ā¦but currently it seems a bit convoluted.
Iāve tried using invokeLater and invokeAsynchronous to better control the process from activation to finish, but the problem always goes back to āHow do I define when a user is done with this component?ā
the dropdown component is my least favorite input component, however if I were to use one I think I would Place the scripting on the āFocus Gainedā and āFocus Lostā actions.
Sometimes the cleanest solution is a separate āContinueā button that takes a page full of selections and moves the user to the next page, suitably filled in.
They should only execute when the operator has āfinishedā with the dropdown component. Normally this would be off of focusLost, but that trigger depends on another component stealing focus.
Iāve achieved a level of functionality I am happy with looking for the āEnterā key press but ideally if the focusLost triggered a bit differently it would suffice.
Thank you for your copious contributions. Pls go easy on me, I'm a novice programmer. I've tried adding your code as a "Custom Method" of the dropdown component. I was unable to figure out how to incorporate scripting with a "Custom Property". I added pseudo code comments to help me think through what is happening as follows (Am I even close?):
def DropdownSelectInvis(self):
'''
Some words about arguments, and not including self
as a redundant argument
'''
#Import the PopupMenuListener java class in order to subclass it's features
#for the dropdown list/box.
from javax.swing.event import PopupMenuListener
#Create python class with functions for handling initiation and to get
#invisibility property and set it to the invisible state.
class myPopUpMenuListener(PopupMenuListener):
def __init__(self, myDropDown):
self.dropDown = myDropDown
def popupMenuWillBecomeInvisible(self, e):
print self.dropDown.selectedValue, self.dropDown.selectedStringValue
self.dropDown.myCustomProperty = self.dropDown.selectedValue
#pass the dropdown component to the method for adding it to the subclassed
#listener.
myDropDown = event.source.parent.getComponent('Dropdown')
dd.addPopupMenuListener(myPopUpMenuListener(myDropDown))
This works in the designer but not in my remotely deployed client. Can you help me understand how to understand/resolve this behavior? I feel like I still need to pipe/connect some things up to my actual components/properties...
Hi Sera,
Iāve added a custom method called ādropFocusā on the dropdown in question, and placed the above code in itā¦
Did you put the code from jpark somewhere else?
Iām not seeing the values printed to the console indicating that the second function within the class is not being called.
Iāve created a custom property for the dropdown in question called "myCustomProperty " to see if it gets populated with
the selectedValue string value, but it doesnāt when I change the selected value.
Did you bind the āmyCustomPropertyā on the dropdown component somehow?
What is the āeā argument that is passed to the popupMenuWillBecomeInvisible function?
Waitā¦I think you guys are leveraging off the code already in the focusLost methodā¦updating the custom property forces focus to be lost then??? Giving it a shot. Sorry for the detour.
Your core issue is probably that youāre adding this as a custom method.
Custom methods are just functions available from the component; theyāre not necessarily being called unless you specifically use them in the script. You could add Jaeās code to the propertyChange event handler, and have it run once (note: will only work in a client) using this:
if event.propertyName == 'componentRunning':
from javax.swing.event import PopupMenuListener
class myPopUpMenuListener(PopupMenuListener):
def __init__(self, myDropDown):
self.dropDown = myDropDown
def popupMenuWillBecomeInvisible(self, e):
print self.dropDown.selectedValue, self.dropDown.selectedStringValue
self.dropDown.myCustomProperty = self.dropDown.selectedValue
myDropDown = event.source.parent.getComponent('Dropdown')
dd.addPopupMenuListener(myPopUpMenuListener(myDropDown))
The āeā argument of popupMenuWillBecomeInvisible is the āeventā object thatās automatically passed into the function by Swing when the event happens.
Iāve tried placing jaeās ānakedā class in the existing focusLost method (testing my theory that the focusLost event handler has something built-in that jae was leveraging), and commented out the code in the custom method
I created. (maybe i need to delete it altogether?) but received a name error pointing to āddā (the last line of code of the class in question) I assumed this was ābuilt-inā to the listener but I havenāt read the docs yet, despite my better judgement telling me I should.
The same name error is raised when I deploy the class in the propertyChange method from the client. Curiously, the designer client is behaving as desired (dropdown is retracting when an item is selected) in preview mode-just as it was when the class was placed in the custom method I added. (Thinking I need to check that behavior with all scripting removed now.)
However, if I open or close the window containing the dropdown box while in preview mode, the name error is thrown, indicating at least that the property change event filtered for ācomponentRunningā is workingā¦however, Iāve not seen the console receive any printed values nor has the custom property I created āmyCustomPropertyā been written to with the selectedValue as the function suggests it might.
Thanks for coming along the ride Paul.
Name Error as follows:
File "<event:propertyChange>", line 12, in <module>
NameError: name 'dd' is not defined
at org.python.core.Py.NameError(Py.java:260)
at org.python.core.PyFrame.getname(PyFrame.java:257)
at org.python.pycode._pyx43.f$0(<event:propertyChange>:12)
at org.python.pycode._pyx43.call_function(<event:propertyChange>)
at org.python.core.PyTableCode.call(PyTableCode.java:165)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1275)
at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:626)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:168)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.access$000(ActionAdapter.java:40)
at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter$ActionRunner.run(ActionAdapter.java:280)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Ignition v7.8.4 (b2016082217)
Java: Oracle Corporation 1.8.0_131
Try replacing the DD with a reference to the DropDown Object.
Let me see if I can find an example.
#Pull a Reference to the DropDown Object you want to
YourOwnDD = event.source.parent.getComponent('dd_Filter')
#Then branch from there
#If you call from an event generator on the dropdown
event.source.addPopupMenuListener(myPopUpMenuListener(YourOwnDD))
#If you call from anywhere else.
YourOwnDD.addPopupMenuListener(myPopUpMenuListener(YourOwnDD))
#If you call from a a custom method.
self.addPopupMenuListener(myPopUpMenuListener(YourOwnDD))
if event.propertyName == 'componentRunning':
from javax.swing.event import PopupMenuListener
class myPopUpMenuListener(PopupMenuListener):
def __init__(self, myDropDown):
self.dropDown = myDropDown
def popupMenuWillBecomeInvisible(self, e):
print self.dropDown.selectedValue, self.dropDown.selectedStringValue
self.dropDown.myCustomProperty = self.dropDown.selectedValue
myDropDown = event.source
myDropDown.addPopupMenuListener(myPopUpMenuListener(myDropDown))
Minor change; I hadnāt paid enough attention to what Jae was doing.
Breaking it down: Basically, once the component is initialized it will fire this code once.
This code creates a custom āPopupMenuListenerā (a default Java object) that fires the custom popupMenuWillBecomeInvisible function that sets the custom property value. It holds a reference back to the original dropdown as the second argument to the __init__ function.
Iām remiss in not mentioning that I have the dropdown in āTableā display mode (vs. āListā). Since this seems like it might be a low level event or item listener issue, might this be a factor? (this is me flexing some new knowledge from reading some of the docsā¦Iām not usually this java lingo savy.)
Thanks Seraā¦your initial comment lead me to look at the āpopupTriggerā listed as an event object property under the mouseReleased event handlerā¦Iāll explore your suggestion shortly, but Paul is bring some code suggestions too. Let me see what heās doing.
Hi Paul. Tried the updated code in the propertyChange event handler. Still no dice getting the table to disappear once an item is selected. However, Iāve changed the display mode to āListā from āTableā and the list now disappears when an item is selected, which means users will need to know which city is associated with a particular airport codeā¦
Since the dropdown (JComboBox) is a combination of many components, perhaps the invisible property of the embedded table should be the target of our bit flipping adventure?
I was able to accomplish what I believe you were wanting with this script:
if event.newValue != event.oldValue:
if event.propertyName == āselectedStringValueā:
⦠(execute your function here)