Kivy 布尔对象 属性 不随复选框改变

Kivy boolean object property does not change with checkbox

所以我试图从三个单选按钮中获取值,每个单选按钮都有自己的布尔值分配给它们,即使我的按钮确实改变了它们自己的值,它们似乎并没有改变分配的值value:属性。

这是处理它的 python 代码:

from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.properties import BooleanProperty
from kivy.graphics import *

class CliClicker(BoxLayout):

    blue = ObjectProperty(True)
    red = ObjectProperty(False)
    green = ObjectProperty(False)

    def bg_change(self):
        #Change background according value set in radio buttons
        if self.blue:
            print('color changed to blue')
            with self.menuoptions.canvas:
                Color(rgba=(.7,.7,.9,1))
        elif self.red:
            print('color changed to red')
            with self.menuoptions.canvas:
                Color(rgba=(.9,.7,.7,1))
        elif self.green:
            print('color changed to green')
            with self.menuoptions.canvas:
                Color(rgba=(.7,.9,.7,1))

    def show_value(self, instance, value, box):
        self.value = box
        print(instance, box, self.value)
        print('blue', self.blue)
        print('red', self.red)
        print('green', self.green)

class MainApp(App):

    def build(self):
        return CliClicker()

app = MainApp()
app.run()

我包含了一个用于检查每个值状态的方法

这是代码的 Kivy 部分:

<OptionButton@Button>:
    size_hint: (None,None)
    width: 200
    height: 40

<CliClicker>:
    orientation: "vertical"
    id: cliclicker
    menuoptions: menuopts

    TabbedPanel:
        do_default_tab: False
        height: 200
        id: tabs

        TabbedPanelItem:
            text: "Menu"
            id: menu

            FloatLayout:
                id: menuopts
                canvas:
                    Color:
                        rgba: .7,.7,.9,1
                    Rectangle:
                        pos: self.pos
                        size: self.size

                OptionButton:
                    text: 'Option 1'
                    pos_hint: {'right':.63, 'top':.9}

                OptionButton:
                    text: 'Option 1'
                    pos_hint: {'right':.63, 'top':.8}

                GridLayout:
                    cols: 6
                    size_hint: (None, None)
                    pos_hint: {'top': .7, 'right':.69}
                    height: 40
                    width: 300

                    canvas:
                        Color:
                            rgba: .9,.9,.9,1
                        Rectangle:
                            pos: self.pos
                            size: self.size

                    CheckBox:
                        group: "bg_color"
                        value: root.blue
                        on_active: cliclicker.show_value(self, self.value, self.active)
                        color: 0,0,0,1
                    Label:
                        text: 'blue'
                        color: 0,0,0,1
                    CheckBox:
                        group: "bg_color"
                        value: root.red
                        on_active: cliclicker.show_value(self, self.value, self.active)
                        color: 0,0,0,1
                    Label:
                        text: 'red'
                        color: 0,0,0,1
                    CheckBox:
                        group: "bg_color"
                        value: root.green
                        on_active: cliclicker.show_value(self, self.value, self.active)  
                        color: 0,0,0,1
                    Label:
                        text: 'green'
                        color: 0,0,0,1

我觉得主要是你没看懂下面的意思

value: root.blue

我认为您认为 root.blue 更改如果激活它会更改但反之亦然,您要指出的是每次更改 root.blue 都会更改复选框的状态并且显然你从来没有改变 root.blue 所以活动不会被更新。反之亦然:

<CliClicker>:
    blue: checkbox_blue.active
    # ...
    CheckBox:
        id: checkbox_blue
        group: "bg_color"

但即便如此这也是一个坏主意,考虑到每个功能都是一个接收输入并获得输出的黑盒子总是好的,在这种情况下输出是颜色所以我们创建一个继承的自定义小部件来自 GridLayout 并公开 属性 颜色:

*.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class CliClicker(BoxLayout):
    pass

class MainApp(App):
    def build(self):
        return CliClicker()

if __name__ == '__main__':
    MainApp().run()ç

*.kv

<OptionButton@Button>:
    size_hint: (None,None)
    width: 200
    height: 40

<ColorSelector@GridLayout>:
    cols: 6
    color_sel: (.7,.7,.9,1)
    canvas:
        Color:
            rgba: .9,.9,.9,1
        Rectangle:
            pos: self.pos
            size: self.size
    CheckBox:
        group: "bg_color"
        color: 0,0,0,1
        active: True
        on_active: if self.active: root.color_sel = .7,.7,.9,1
    Label:
        text: 'blue'
        color: 0,0,0,1
    CheckBox:
        group: "bg_color"
        color: 0,0,0,1
        on_active: if self.active: root.color_sel = .9,.7,.7,1
    Label:
        text: 'red'
        color: 0,0,0,1
    CheckBox:
        group: "bg_color"
        color: 0,0,0,1
        on_active: if self.active: root.color_sel = .7,.9,.7,1
    Label:
        text: 'green'
        color: 0,0,0,1

<CliClicker>:
    orientation: "vertical"
    id: cliclicker
    menuoptions: menuopts

    TabbedPanel:
        do_default_tab: False
        height: 200
        id: tabs

        TabbedPanelItem:
            text: "Menu"
            id: menu

            FloatLayout:
                id: menuopts
                color_property:  (.7,.7,.9,1)
                canvas:
                    Color:
                        rgba: self.color_property
                    Rectangle:
                        pos: self.pos
                        size: self.size

                OptionButton:
                    text: 'Option 1'
                    pos_hint: {'right':.63, 'top':.9}

                OptionButton:
                    text: 'Option 1'
                    pos_hint: {'right':.63, 'top':.8}
                ColorSelector:
                    id: selector
                    size_hint: (None, None)
                    pos_hint: {'top': .7, 'right':.69}
                    height: 40
                    width: 300
                    on_color_sel: menuopts.color_property = self.color_sel