Problem sub-classing ControlButton
#1
Here's the gist...
PHP Code:
class Button(xbmcgui.ControlButton):
    
def afunc(self):
        return 
"Success!!"

class MyDialog(xbmcgui.WindowDialog):
    
def __init__(self):
        
self.button Button(00100100"Click Me")
        
self.addControl(self.button)
        
self.setFocus(self.button)
    
    
def onControl(selfcontrol):
        if 
control == self.button:
            
msg control.afunc()

dialog MyDialog()
dialog.doModal() 

When you click the button in the top-left of the screen you get the exception
Code:
'xbmcgui.ControlButton' object has no attribute 'afunc'

Why is this happening? I'm sure I've seen this sort of sub-classing of controls done before. Am I doing something obviously wrong?

I'm using a recent Gotham build on Linux and Windows.

Here is an add-on to test it: script.control.zip
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#2
(deleted as not relevant)
Reply
#3
I just tried the above and got exactly the same error.

I tried to remember where I'd seen a ControlButton subclass before and eventually found this https://github.com/lextoumbourou/plugin....ontrols.py

Are you saying that add-on won't work?
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#4
(2014-02-24, 15:51)Leopold Wrote: I just tried the above and got exactly the same error.

I tried to remember where I'd seen a ControlButton subclass before and eventually found this https://github.com/lextoumbourou/plugin....ontrols.py

Are you saying that add-on won't work?

I'm very sorry for my mistake. Please disregard my previous post as being incorrect. I remember that I have faced the same issue when creating my PyXBMCt framework and actually haven't been able to solve it.
Yes, you can sub-class xbmcgui Controls, but you cannot make onControl method of the container window class execute your added methods because it receives not a sub-classed Control instance but actually a parent class instance (xbmcgui.ControlButton in your case) which is indeed C++ exposed via SWIG.
To put it simple: onControl() does not know anything about your added methods.
Reply
#5
OK yes that seems to be the case based on my tests. I think that part of the plugin I linked to doesn't work.

I will still subclass ControlButton just to make its construction easier. Something like this:

PHP Code:
class MoveButton(xbmcgui.ControlButton):

    
WIDTH HEIGHT 32
    TEXTURE_FMT 
__cwd__ os.sep '{}.png'

    
def __new__(clsxydirection):
        
focusTexture cls.TEXTURE_FMT.format(direction '-focus')
        
noFocusTexture cls.TEXTURE_FMT.format(direction)
        return 
super(MoveButtoncls).__new__(clsxycls.WIDTHcls.HEIGHT""focusTexturenoFocusTexture)

button1 MoveButton(00'up')
button2 MoveButton(032'down'
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#6
(2014-02-24, 17:14)Leopold Wrote: OK yes that seems to be the case based on my tests. I think that part of the plugin I linked to doesn't work.

It works because no methods, added to C++/SWIG classes, are called in onControl().
Just to be clear: you can sub-class xbmcgui.Controls and you can call your added methods in your Python code. But you cannot call your added methods if a Control instance is received via onControl() as the 2-nd positional argument (besides self). So your code in the 1-st post won't work. But this code will work:
PHP Code:
def afunc():
    return 
"Success!!"

class MyDialog(xbmcgui.WindowDialog):
    
def __init__(self):
        
self.button xbmcgui.ControlButton(00100100"Click Me")
        
self.addControl(self.button)
        
self.setFocus(self.button)
    
    
def onControl(selfcontrol):
        if 
control == self.button:
            
msg afunc()

dialog MyDialog()
dialog.doModal() 
I understand it's tricky and it took some time for me to figure it out, but this C++/Python mix works this way.
Reply
#7
It's strange because this line calls the method canUpdateLabel() added to ControlButton, in onControl()
https://github.com/lextoumbourou/plugin....ls.py#L165
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#8
(2014-02-24, 18:36)Leopold Wrote: It's strange because this line calls the method canUpdateLabel() added to ControlButton, in onControl()
https://github.com/lextoumbourou/plugin....ls.py#L165

Yes, but it is not called on a Control instance received via onControl() argument. In your example only methods of a parent C++ class (setLabel) are called.
Once again:
PHP Code:
class Button(xbmcgui.ControlButton):
    
def afunc(self):
        return 
"Success!!"

class MyDialog(xbmcgui.WindowDialog):
    
def __init__(self):
        
self.button Button(00100100"Click Me")
        
self.addControl(self.button)
        
self.setFocus(self.button)

    
def onControl(selfcontrol):
        if 
control == self.button:
            
msg control.afunc() # WRONG!!! control is not an instance of the sub-classed self.button but a parent xbmcgui.ControlButton!
                                            # xbmcgui.ControlButton instance does not have afunc() method!
            
msg self.button.afunc() # Correct! We are calling a method of a sub-classed instance directly by name.

dialog MyDialog()
dialog.doModal() 
Again, this may be hard to understand but in the comparison control == self.button we are actually comparing different objects (a xbmcgui.ControlButton istance and Button instance) via overloaded comparison operator which allows such comparison.
Reply
#9
Yes I see now, I don't know how I missed that! Thanks a lot for your help with this.
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply

Logout Mark Read Team Forum Stats Members Help
Problem sub-classing ControlButton0