简体   繁体   中英

Kivy - cannot change button state from function outside kv language

I am trying to change the state of a ToggleButton from a function.

The only way I've been able to get the state change to work is if the function that changes the state is within the root widget AND I call that function from kv language.

Here is some simplified code I set up to test the problem:

python code:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

class MainPanel(BoxLayout):
    def togOn(self):
        self.ids.node1_power.state = 'down'

class avcsServerApp(App):
    def build(self):
        global root
        root = self.root
        return Builder.load_file('avcsserver.kv')

    def press(self):
        root.togOn()

if __name__ == '__main__':
    avcsServerApp().run()

kv code:

<Button>:
    font_size: 20
    color: .12,.13,.14,1
    border: 25, 25, 25, 25
    background_down: 'buttono.png'
    background_normal: 'button.png'

MainPanel:
    canvas:
        Color:
            rgba: .12,.13,.14,1
        Rectangle:
            pos: self.pos
            size: self.size
    ToggleButton:
        id: node1_power
        text: "POWER"
    Button:
        text: "TOGGLE"
        on_release: app.press()

When calling the togOn() function straight from the kv code (ie on_release: root.togOn() ), it works as expected, but calling it through press() fails to update the button state.

Alternatively, putting something like root.ids.node1_power.state = 'down' directly in the press() function does not work either.

I suspect the method I'm using to reference the root widget through my Python code is to blame, as it doesn't seem proper (the global root and root=self.root lines), but I'm new to Kivy and Python, and it was the only way I have found to do so.

The whole global root is really a bad idea. You were very close. The following python code should work as you intend it.

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

class MainPanel(BoxLayout):
    # Not need for the togOn method
    pass

class avcsServerApp(App):
    def build(self):
        return Builder.load_file('avcsserver.kv')

    def press(self):
        # The root attribute is readily available inside the app 
        # class instance. 
        self.root.ids.node1_power.state = "down" if \
            self.root.ids.node1_power.state != "down" else "normal"

if __name__ == '__main__':
    avcsServerApp().run()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM