Kivy - Kv - ScreenManager - 改变当前屏幕
Posted
技术标签:
【中文标题】Kivy - Kv - ScreenManager - 改变当前屏幕【英文标题】:Kivy - Kv - ScreenManager - changing the current screen 【发布时间】:2018-05-25 20:18:50 【问题描述】:我正在尝试在kivy(kv)中做一个非常简单的例子如下:
#:import Toolbar kivymd.toolbar.Toolbar
BoxLayout:
orientation: 'vertical'
Toolbar:
id: toolbar
title: 'My Toolbar'
md_bg_color: app.theme_cls.primary_color
background_palette: 'Primary'
background_hue: '500'
left_action_items: [['arrow-left', app.root.ids.scr_mngr.current = 'screen1' ]]
right_action_items: [['arrow-right', app.root.ids.scr_mngr.current = 'screen2' ]]
ScreenManager:
id: scr_mngr
Screen:
name: 'screen1'
Toolbar:
title: "Screen 1"
Screen:
name: 'screen2'
Toolbar:
title: "Screen 2"
这将失败,因为 left_action_items 和 right_action_items 都需要一个对列表:[name_of_icon, expression]。另一方面,当您处理按钮时,该语句将是合法的,例如,如果我们执行以下操作:
on_release:
app.root.ids.scr_mngr.current = 'screen1'
另一方面,left_action_item 的正确方法是:
left_action_items: [['arrow-left', lambda x: app.root.ids.scr_mngr.current = 'screen1' ]]
但是这是不合法的,因为你不能在 python 下的 lambda 中执行这样的赋值。
left_action_items 改变屏幕的正确方法是什么?
【问题讨论】:
【参考方案1】:这是我发现点击 MDToolbar 图标更改屏幕的最简单方法:
main.py
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.lang import Builder
Builder.load_file("telas.kv")
class Tela1(Screen):
pass
class Tela2(Screen):
pass
class MainApp(MDApp):
def build(self):
self.sm = ScreenManager(transition=NoTransition())
self.sm.add_widget(Tela1(name="tela1"))
self.sm.add_widget(Tela2(name="tela2"))
return self.sm
def change_screen(self, tela):
self.sm.current = tela
if __name__ == "__main__":
MainApp().run()
telas.kv
<Tela1>:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "My App"
MDRoundFlatButton:
text: "Go to Tela 2"
on_release: app.root.current = "tela2"
MDLabel:
text: "Tela 1"
<Tela2>:
BoxLayout:
orientation: "vertical"
MDToolbar:
title: "Tela 2"
left_action_items: [["arrow-left", lambda x: app.change_screen("tela1")]]
MDLabel:
text: "Tela 2"
【讨论】:
【参考方案2】:你可以把你的根类变成一个 python 类,并在那里有一个 change_screen 方法。还将您的屏幕管理器设置为根类中的 ObjectProperty。 然后在 kv 中使用 partial 以便能够将参数传递给方法。 试试这样:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemeManager
class MyLayout(BoxLayout):
scr_mngr = ObjectProperty(None)
def change_screen(self, screen, *args):
self.scr_mngr.current = screen
KV = """
#:import Toolbar kivymd.toolbar.Toolbar
#:import partial functools.partial
MyLayout:
scr_mngr: scr_mngr
orientation: 'vertical'
Toolbar:
id: toolbar
title: 'My Toolbar'
left_action_items: [['arrow-left', partial(root.change_screen, 'screen1') ]]
right_action_items: [['arrow-right', partial(root.change_screen, 'screen2') ]]
ScreenManager:
id: scr_mngr
Screen:
name: 'screen1'
Toolbar:
title: "Screen 1"
Screen:
name: 'screen2'
Toolbar:
title: "Screen 2"
"""
class MyApp(App):
theme_cls = ThemeManager()
def build(self):
return Builder.load_string(KV)
MyApp().run()
【讨论】:
它有效。遗憾的是,ScreenManager 没有提供执行以下操作的可能性: set_screen('screen1')【参考方案3】:有多种选择,你可以做
left_action_items: [('arrow-left', (app.root.ids.scr_mngr, 'current', 'screen1'))]
然后再做:
for icon, expr in self.left_action_items:
setattr(*expr)
如果你真的想要一个可执行的表达式,你可以这样做:
left_action_items: [('arrow-left', lambda: setattr(app.root.ids.scr_mngr, 'current' 'screen1'))]
【讨论】:
【参考方案4】:还有一种方法。我使用的:
left_action_items: [['arrow-left', lambda x: root.manager.change_screen("main_screen")]]
屏幕管理器内部函数change_screen()的实现:
def change_screen(self, screen):
# the same as in .kv: app.root.current = screen
self.current = screen
【讨论】:
以上是关于Kivy - Kv - ScreenManager - 改变当前屏幕的主要内容,如果未能解决你的问题,请参考以下文章
如何:main.py,带有 kivy 轮播代码的新类,kv 文件
Kivy 无法使用 ScreenManager 获取文本输入