Kivy 的 ScreenManager 和 Popups 不想一起工作

Kivy's ScreenManager and Popups don't want to work together

如标​​题所述 - 我被卡住了。我一直在研究代码,只要我将 ScreenManager 和 Popup 分开,一切都会正常进行。一旦合并 - 他们拒绝合作。无论如何,这是显示我遇到的问题的简单应用程序。

from kivy.lang import Builder
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import Screen, ScreenManager

class First(GridLayout,Screen):
    def show_popup(self):
        Popp().open()
    pass

class Second(Screen):
    pass

class Popp(Popup):
    pass

class ScreenManagement(ScreenManager):
    pass

app = Builder.load_file("main.kv")

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


if __name__ == "__main__":
    MainApp().run()

和main.kv文件

ScreenManagement:
    First:
    Second:

<First>:
    name:"First"
    rows: 2
    Button:
        text: "FirstButton"
        on_release: app.root.current = "Second"
    Button:
        text: "Show popup"
        on_release: root.show_popup()

<Second>:
    name:"Second"
    Button:
        text: "BUTTON"
        on_release: app.root.current = "First"

<Popp>:
    title: "testing"
    text: "Hello world"
    size_hint: None,None
    size: 400,400
    auto_dismiss: False
    Button:
        text: "Okay"
        on_press: root.dismiss()

应用程序启动,第一个和第二个屏幕正在运行,但当我尝试弹出窗口时,我最终得到:

kivy.uix.popup.PopupException: Popup can have only one widget as content

Screen 以某种方式被视为 Popp 内部的一个小部件?还是我误解了 kivy 文档?

这是加载kv文件的错误,在这种情况下应该抛出异常。

您在代码中所做的是两次加载 kv 文件,这会导致一些奇怪的行为。只需删除 Builder.load_file(..) 即可。该文件将自动加载。

此外,永远不要像 class First(GridLayout, Screen) 那样对小部件进行双重子类化,因为这可能会导致一些问题。相反,在屏幕内创建一个网格布局。

将Popup中的元素放在布局中,例如:Boxlayout。

我的意思是:

<Popp>:
    title: "testing"
    BoxLayout:
        orientation: 'vertical'
        size_hint: None,None
        size: 400,400
        Label:
           text: "Hello world"
        Button:
            text: "Okay"
            on_press: root.dismiss()

我在使用 kivy Builder.load_file 和 Popup 时遇到同样的问题,它们不能一起工作。 解决方案很简单,在 python 代码端构建弹出窗口。这是一个加载弹出窗口示例:

python:

    from kivy.app import App
    from kivy.uix.popup import Popup
    from kivy.factory import Factory
    from kivy.properties import ObjectProperty
    from kivy.clock import Clock
    from kivy.lang import Builder
    from kivy.uix.popup import Popup
    from kivy.uix.image import Image
    from kivy.uix.label import Label
    from kivy.uix.boxlayout import BoxLayout

    import time, threading


    buildKV = Builder.load_file("example.kv")

    class ExampleApp(App):
        def show_popup(self):
            content = BoxLayout(orientation= "vertical")
            image=Image(source= 'files/loading.gif', anim_delay= 0)
            label=Label(text= 'Model is Running.\nBe Patient Please.')
            content.add_widget(image)
            content.add_widget(label)
            self.popup = Popup(title='Model is Running.',
                      size_hint=(.250, .785),
                      content=content, auto_dismiss=False)

            self.popup.open()

        def process_button_click(self):
            # Open the pop up
            self.show_popup()

            # Call some method that may take a while to run.
            # I'm using a thread to simulate this
            mythread = threading.Thread(target=self.something_that_takes_5_seconds_to_run)
            mythread.start()

        def something_that_takes_5_seconds_to_run(self):
            thistime = time.time()
            while thistime + 10 > time.time(): # 5 seconds
                time.sleep(1)

            # Once the long running task is done, close the pop up.
            self.pop_up.dismiss()

    if __name__ == "__main__":
        ExampleApp().run()

基维:

   BoxLayout:
        Button:
            height: 40
            width: 100
            size_hint: (None, None)
            text: 'Click Me'
            on_press: app.process_button_click()