Kivy:使用 on_press 事件在屏幕管理器中更改屏幕
Posted
技术标签:
【中文标题】Kivy:使用 on_press 事件在屏幕管理器中更改屏幕【英文标题】:Kivy: Changing screens in screen manager with an on_press event 【发布时间】:2013-10-29 18:06:06 【问题描述】:我想知道如何使用绑定到按钮的 on_press 事件来更改屏幕,而不使用 KV 文件/KV 语言。
我已通读 Kivy 文档,但只能使用 KV 文件找到解决方案。
例子:
on_press: root.manager.current = 'screen2'
我还可以使用以下方法更改主 python 文件中的屏幕:
screenmanager.current = 'screen2'
但我不知道如何使用按钮来达到同样的效果。
【问题讨论】:
【参考方案1】:一个有两个屏幕的工作示例,没有 kv 文件,一切都在 Python 中完成:
import kivy
kivy.require('1.8.0')
from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class ScreenOne(Screen):
def __init__ (self,**kwargs):
super (ScreenOne, self).__init__(**kwargs)
my_box1 = BoxLayout(orientation='vertical')
my_label1 = Label(text="BlaBlaBla on screen 1", font_size='24dp')
my_button1 = Button(text="Go to screen 2",size_hint_y=None, size_y=100)
my_button1.bind(on_press=self.changer)
my_box1.add_widget(my_label1)
my_box1.add_widget(my_button1)
self.add_widget(my_box1)
def changer(self,*args):
self.manager.current = 'screen2'
class ScreenTwo(Screen):
def __init__(self,**kwargs):
super (ScreenTwo,self).__init__(**kwargs)
my_box1 = BoxLayout(orientation='vertical')
my_label1 = Label(text="BlaBlaBla on screen 2",font_size='24dp')
my_button1 = Button(text="Go to screen 1",size_hint_y=None, size_y=100)
my_button1.bind(on_press=self.changer)
my_box1.add_widget(my_label1)
my_box1.add_widget(my_button1)
self.add_widget(my_box1)
def changer(self,*args):
self.manager.current = 'screen1'
class TestApp(App):
def build(self):
my_screenmanager = ScreenManager()
screen1 = ScreenOne(name='screen1')
screen2 = ScreenTwo(name='screen2')
my_screenmanager.add_widget(screen1)
my_screenmanager.add_widget(screen2)
return my_screenmanager
if __name__ == '__main__':
TestApp().run()
【讨论】:
是否有特殊原因导致这不适用于 Kivy 1.9.2?【参考方案2】:实现此目的的一种简单方法是定义您自己的按钮子类:
class ScreenButton(Button):
screenmanager = ObjectProperty()
def on_press(self, *args):
super(ScreenButton, self).on_press(*args)
self.screenmanager.current = 'whatever'
按下按钮时会自动调用on_press方法,所以screenmanager的current
属性会发生变化。
然后你可以有类似的代码:
sm = ScreenManager()
sc1 = Screen(name='firstscreen')
sc1.add_widget(ScreenButton(screenmanager=sm))
sc2 = Screen(name='whatever')
sc2.add_widget(Label(text='another screen'))
sm.add_widget(sc1)
sm.add_widget(sc2)
单击按钮应根据需要切换屏幕。
另一种方式(这可能是 kv 语言的实际操作方式)是手动使用 bind
方法。
def switching_function(*args):
some_screen_manager.current = 'whatever'
some_button.bind(on_press=switching_function)
这意味着只要按下some_button
,就会调用switching_function
。当然,关于如何以及何时定义函数,这里有很大的灵活性,因此(例如)您可以做一些更一般的事情,比如将屏幕管理器作为第一个参数传递给函数。
我没有测试这段代码,它不是一个完整的应用程序,但希望含义清楚。任何一种方法都应该可以正常工作,您可以选择看起来最明智的方法。稍后我可能会构建一个更完整的示例。
【讨论】:
感谢您的回答。使用子类解决方案帮助我实现了我想要做的事情。再次感谢。【参考方案3】:另一种解决方案,是使用 EventDispatcher 的setter
方法,获取 screen_manager.current 的 setter 函数的引用
button.bind(on_press=partial(sm.setter('current'), (sm, 'whatever'))
当然,它不是很性感,这就是为什么 kv 通常是解决这些问题的更清洁的解决方案,但它应该可以工作。
ps:如果您不知道,partial
来自 functools
模块,使用预加载参数构建此类回调通常很有用。
【讨论】:
我对 kivy 还很陌生,所以性感在我的名单上并不高。这对我来说非常方便。谢谢。以上是关于Kivy:使用 on_press 事件在屏幕管理器中更改屏幕的主要内容,如果未能解决你的问题,请参考以下文章
如何在.kv文件中按钮的on_press事件中隐藏画布和矩形
如何使用On_Press更改动态创建的小部件的BG颜色并使用Pickle保存? (与Kivy的Python)