Bug: event.source.setValue on One-Shot Button does not return expected value

Reading the setValue property on the One Shot Button in a script, returns an object rather than the value of the property.

Ignition Version: 8.1.27 (b2023042509)

The script (propertyChange):

if event.propertyName == "value":
	
	print event.newValue
	print event.source.value
	print event.source.setValue
	
	if event.source.value == event.source.setValue:
		print "in"
		
		event.source.value = 0

Console Result:

1
1
<bound method com.inductiveautomation.factorypmi.application.components.PMIControlButton.setValue of com.inductiveautomation.factorypmi.application.components.PMIControlButton[One Shot Button,0,0,68x61,disabled,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.synth.SynthBorder@46f3df97,flags=16777504,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=110,height=27],defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=java.awt.Insets[top=0,left=0,bottom=0,right=0],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Writing...,defaultCapable=true]>

It's supposed to be:event.source.setValue(PASSNewValueHere)

This is a method for changing the value not a field.

It's an issue with the name of the property colliding with the name of the property accessor methods for the value property.

You won't be able to use Jython's automatic property syntax - you can refer to the value you care about using event.source.getSetValue() and event.source.setSetValue(newValue).

1 Like

It is a property, that is set in the vision property editor. I should be able to read from it.
If I wanted to set the value, I would do so directly with event.source.value = 0.

getSetValue() works.

Still, I selected the property with the scripting "Insert Property Reference" property selector, I believe it should work like any other property selected in this way.

You're not wrong that it should "just work", but in order to actually do that we'd have to add a new property to the one-shot button with a different name and have the property selector use that. Doable, but low priority given the low rate of occurrence and the easy workaround. Plus, what do we name it? setValue2?

The underlying issue is that every component property has a getX and setX method, and there's no way for Jython to distinguish between a call to setValue() (meaning update the value property) and setValue (meaning give me the current set value of the component).

I was mistaken. setValue exists in the class as both a field and a method:
Test Button Script:

oneShotButton = event.source.parent.getComponent('One Shot Button')
	for field in oneShotButton.getClass().getDeclaredFields():
		if field.name == 'setValue':
			print 'Field Name = ', field.name
			field.setAccessible(True)
			setValueField = field.get(oneShotButton)
			print 'Field Type = ', type(setValueField)
			print
	for method in oneShotButton.getClass().getDeclaredMethods():
		if method.name == 'setValue':
			print 'Method Name = ', method.name
			print type(oneShotButton.setValue)

Output:

Field Name =  setValue
Field Type =  <type 'int'>

Method Name =  setValue
<type 'instancemethod'>

That said, the declared field is not in the documentation for that component. Only the method is listed:

Yeah. It's because Jython. Instead of requiring you to go to the class and reflectively look up the methods as Java does, Jython follows the Python model of allowing you to look up instance methods as first-class objects, so myClass.myInstanceMethod == bound method of myClass, and myClass.myInstanceMethod() == a call to that bound method. It doesn't show in the Javadocs because it's not "real", it's only there inside the Jython environment.

Looking closer at the docs, the field is technically listed there as an argument in the setSetValue method and as a returned value for the getSetValue method.

...but even so, I realize that my initial answer was correct, and at this point, I've way over analyzed this.

But it wasn't. You were conflating the setter for the value NetBeans property with the setValue property, whose setter is setSetValue(). But the two different NetBeans properties clash in jython because jython exposes both the native java methods and the implicit jython fields. Except it cannot in this case, due to the poor choice of name. (The setValue property could exist in this scheme if the value property did not exist.)

1 Like

Yesterday, I was reading and replying to this from my phone, and everything looked good, but this morning, I was reading the forum from my computer, and uggh! ...that screenshot I posted of the setSetValue method rendered offensively large. The text is clear enough that the picture isn't necessary, so I've removed it. My apologies if that came across as obnoxious.

It did not strike me so. No worries.

FWIW, this topic might help: