This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
tableViewCell how to bind methods as action callbacks
zencuke102 last edited by ccc
I'm creating a custom TableView but can't figure out how to pass an instance method to Switch.action. I can bind a function but I want to implement multiple rows with the same class and all my attempts fail. I'm trying wrapping the method in a lambda but can't get the args right. The link below fails when a switch is switched. It fails with "TypeError:unbound method checkAction() must be..." The error dialog clips the rest of the message which is not helpful. If I knew what it "must be..." I might be able to fix it. I consider this a bug in the ui error handler. The full error message should be accessable somehow.
Any hints, either to get a complete error message or to fix the method binding would be greatly appreciated.
cvp last edited by cvp
@zencuke102 I don't understand your problem. This is ok, isn't it ?
s.action = switchActionOnce
Anyway, in your GitHub script, the t.frame was not wide enough to see the switch, I changed to
t.frame = (2, 2, 350, 280)
cvp last edited by cvp
If you use the same function for several switchs and you want to know which switch has been actionned, you could save at its creation, by example, the used prompt.
s.prompt = prompt s.action = switchActionOnce
then, you can use it in the action code, like
def switchActionOnce(sender): # instead of val, it is usual to use 'sender' print('switchActionOnce:',sender.prompt,'=',sender.value)
Another remark: enabled attribute of controls is a boolean value, so don't set
xxx.enabled = 0 but xxx.enabled = False.
When set to False, the switch is grayed out and its value cannot be changed by the user"
Last remark: don't use SwitchAction also as an action for your TextField...
zencuke102 last edited by zencuke102
@cvp That looks good. I did intend to use the prompt as you suggest but I was going to store it in the class I was building which creates the TableViewCell. I didn't get that far in developing the code because I couldn't figure out how to bind an instance method from new()
which doesn't have an instance (self) pointer. It only gets a class pointer. I'm still confused about new vs init and what you can do in which. (And I should be running this in python 3. I keep forgetting the default is still set to 2.7. I should fix that.)
It didn't occur to me that I could store data (ie the prompt value) in the Switch instance itself so I don't need to bind the action to a class method. I am still not used to the flexibility of Python. Based on this I really should discard all the new classes in this code except for the data_souce class and focus on storing 'instance' data in the widget objects and then use simple functions as callbacks and to encapsuate whatever functionality is left. And then put all the gui stuff in its own namespace.
Your other comments are completely valid and I thank you but they are mostly a result of being half way through a code restructure. For example the Number class started as a cut and paste of the other class and I hadn't gotten to updating the TextField action. I've been totally blocked on the action bind problem. I should have created and posted a stripped down version which only showed the action binding error and not waste everyone's time looking at code I already knew was wrong. My apologies.
Note: Setting Switch.enabled = 0 instead of False may be wrong but it works. ```
zencuke102 last edited by
Fixed. Thanks to @cvp. Much appreciated. I updated the github version if anyone wants to see a simple example of a custom tableView which each TableViewCell created independenly, each with independently generated content format. Done with simplest python I could think of (no classes etc.) The only complexity is implementing the custom TableView. You can take this as a template and add your own favorite Python complexity. ;-)
cvp last edited by
Setting Switch.enabled = 0 instead of False may be wrong but it works
You're right but as s.enabled is a Boolean, you could have surprise, try
import ui s = ui.Switch() s.enabled = 7 print(s.enabled)
any non-zero int will give True