Kivy 时钟和弹出窗口

2022-01-15 00:00:00 python kivy kivy-language

问题描述

如何正确地为 switch_id 和 switch_id_popup 创建活动属性,以便可以使用 kivy 时钟在 timer_loop 内创建条件语句?

How do I properly create active properties for switch_id and switch_id_popup so I can create a conditional statement inside of timer_loop with kivy clock?

我在一个类似问题上得到了很好的反馈(再次感谢 eyllanesc),但由于涉及到弹出窗口,我无法采纳建议.

I got great feedback on a similar question(thanks again eyllanesc), but I am unable to incorporate advice now that popup is involved.

下面是说明我的问题的草图.我已经用箭头标识了所有有问题的区域.预先感谢您的任何帮助.

Below is a sketch that illustrates my issue. I have identified all of the areas in question with arrows. Thank you in advance for any help.

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
import time
from kivy.uix.popup import Popup

theRoot = Builder.load_string('''

<CustomPopup1>:

    StackLayout:
        active2: switch_id_popup.active #<---- switch_id_popup declared here(active2)


        Switch:                         #<---- This switch (switch_id_popup)
            id: switch_id_popup
            size_hint: .5, .5
            active: switch_id_popup.active

        Button:
            text: 'Close'
            on_release: root.dismiss()
            size_hint: .5, .5



StackLayout:
    active1: switch_id.active           #<---- switch_id declared here(active1)
    orientation: 'lr-tb'
    padding: 10
    spacing: 5


    Label:
        text: "Zone 1 Valve"
        size_hint: .25, .1

    Switch:                             #<---- This switch (switch_id)
        id: switch_id
        size_hint: .25, .1
        active: switch_id.active


    Button:
        text: "Program 1"
        on_press: app.open_popup1()
        size_hint: .5,.1

''')


class CustomPopup1(Popup):
    pass

class theApp(App):


    def build(self):
        Clock.schedule_interval(self.timer_loop, 2)
        return theRoot


    def timer_loop(self, dt):  

        if theRoot.active1 and theRoot.active2: #<---- How do I make this work if switch_id_popup is within a popup?
            print("Do something")
        else:
            print("Do nothing")

    def open_popup1(self):
        the_popup = CustomPopup1()
        the_popup.open()


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


解决方案

正如我在我之前的解决方案中提到的,你应该将每个类视为一个黑盒,并公开允许您获取和建立值的属性.对于 Popup,active 属性必须是类的一部分,而不是内部 StackLayout.另一方面,在 open_popup 方法中,您总是在创建一个新的 Popup,当您关闭它时将删除它,使该属性不可访问,因此我们推断必须有一个具有更大范围的 Popup 对象,因为它必须在外部创建App 类的成员或成为它的成员.最后,active2 不是 theRoot 的属性.

As I mentioned in my previous solution, you should consider each class as a black box and expose properties that allow you to obtain and establish values. In the case of Popup, the active property must be part of the class and not the internal StackLayout. On the other hand in the open_popup method you are always creating a new Popup that will be deleted when you close it making the property is not accessible, so we deduce that there must be a Popup object with a larger scope for it must be created outside of theApp class or be a member of it. Lastly, active2 is not a property of theRoot.

综合以上,得到如下解决方案:

Considering the above, the following solution is obtained:

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
import time
from kivy.uix.popup import Popup

theRoot = Builder.load_string('''
<CustomPopup>:
    active: switch_id_popup.active
    StackLayout:
        Switch:
            id: switch_id_popup
            size_hint: .5, .5
        Button:
            text: 'Close'
            on_release: root.dismiss()
            size_hint: .5, .5

StackLayout:
    active: switch_id.active
    orientation: 'lr-tb'
    padding: 10
    spacing: 5
    Label:
        text: "Zone 1 Valve"
        size_hint: .25, .1
    Switch:
        id: switch_id
        size_hint: .25, .1
    Button:
        text: "Program 1"
        on_press: app.open_popup()
        size_hint: .5,.1

''')

class CustomPopup(Popup):
    pass


class TheApp(App):
    def build(self):
        self.the_popup = CustomPopup()
        Clock.schedule_interval(self.timer_loop, 2)
        return theRoot

    def timer_loop(self, dt):  
        if self.root.active and self.the_popup.active:
            print("Do something")
        else:
            print("Do nothing")

    def open_popup(self):
        self.the_popup.open()


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

相关文章