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()
如标题所述 - 我被卡住了。我一直在研究代码,只要我将 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()