我在理解Python和Kivy语言之间的沟通方面遇到了问题 - 下面更具体地说。
我有一个应用 - TutorialApp
,build
方法返回MyScreenManager()
。 MyScreenManager
只管理一个名为FirstScreen
的屏幕。在相应的tutorial.kv
文件中,我使用FirstScreen
BoxLayout
id: box
小部件。我们说我有一个清单
FILMS = ['Film 1', 'Film 2']
现在,当我运行应用程序时,我想为每部电影添加一个Button
小部件到BoxLayout
,标识为box
。这应该只进行一次,所以我想把它放在__init__
函数中,我用super
方法覆盖它。这是我的main.py
文件:
#!/usr/bin/env python
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
FILMS = ['Film 1', 'Film 2']
class TutorialApp(App):
def build(self):
return MyScreenManager()
class MyScreenManager(ScreenManager):
pass
class FirstScreen(Screen):
def __init__(self, **kvargs):
super(FirstScreen, self).__init__(**kvargs)
for film in FILMS:
self.ids.box.add_widget(Button(text=film))
if __name__ == '__main__':
TutorialApp().run()
这是我的tutorial.kv
文件:
<MyScreenManager>:
FirstScreen:
<FirstScreen>:
name: 'FirstScreen'
BoxLayout:
id: box
但我的方法不起作用。为什么?可能是因为当时调用__init__
时没有BoxLayout
并且没有id,所以我无法引用它们(至少这是我认为基于日志的内容) ,也通过在不同时间打印self.ids
来测试它。
现在,我能做的是以下内容。我可以像这样简单地调整代码(仅显示更改的部分),而不是在BoxLayout
tutorial.kv
文件中创建:
class FirstScreen(Screen):
def __init__(self, **kvargs):
super(FirstScreen, self).__init__(**kvargs)
box = BoxLayout(id='box')
for film in FILMS:
box.add_widget(Button(text=film))
self.add_widget(box)
tutorial.kv
:
<MyScreenManager>:
FirstScreen:
<FirstScreen>:
name: 'FirstScreen'
这有效,但后来我遇到了其他问题。假设我有更多屏幕,并且我想向Button
添加FirstScreeen
,这将导致不同的屏幕(示例中未指定)。因此,Button
将在tutorial.kv
内指定,如下所示:
Button:
text: 'Go somewhere else'
on_release: app.root.current = 'DifferentScreenName'
但是由于我在__init__
函数中创建了这个框,我不能简单地将这段代码放在tutorial.kv
中。我可以像这样更改main.py
:
class FirstScreen(Screen):
def __init__(self, **kvargs):
super(FirstScreen, self).__init__(**kvargs)
box = BoxLayout(id='box')
for film in FILMS:
box.add_widget(Button(text=film))
box.add_widget(Button(text='Go somewhere else',
on_release="""WHAT SHOULD GO HERE?"""))
self.add_widget(box)
但是用这个词来表示什么应该去?我不知道如何更改屏幕。所以,希望你能理解这个问题。我不知道哪种方式更好,我认为,在*.kv
文件中指定应用布局的内容越多越好,但如何解决与此类似的情况?
首先猜测
在on_init/on_start
内调用tutorial.kv
之类的内容,例如:
<MyScreenManager>:
FirstScreen:
DifferentScreen:
<FirstScreen>:
name: 'FirstScreen'
BoxLayout:
id:box
on_start: root.method_which_adds_film_buttons
Button:
text: 'Go somewhere else'
on_release: app.root.current ='DifferentScreen'
希望,当FirstScreen
初始化时,这种方法只运行一次。但我找不到这样的方法。
第二次猜测
像这样调整__init__
功能:
class FirstScreen(屏幕):
def __init__(self, **kvargs):
super(FirstScreen, self).__init__(**kvargs)
box = BoxLayout(id='box')
for film in FILMS:
box.add_widget(Button(text=film))
box.add_widget(Button(text='Go somewhere else',
on_release=app.root.current('DifferentScreen')))
self.add_widget(box)
或者这个:
class FirstScreen(Screen):
def __init__(self, **kvargs):
super(FirstScreen, self).__init__(**kvargs)
box = BoxLayout(id='box')
for film in FILMS:
box.add_widget(Button(text=film))
box.add_widget(Button(text='Go somewhere else',
on_release=self.root.current('DifferentScreen')))
self.add_widget(box)
两者都没有明显的效果(这就是我在这里问的原因)。这两个例子都显示,我不明白root
是如何传递的。有人可以解释/给出我正在寻找的行为的实例吗?
答案 0 :(得分:1)
感谢Kivy IRC用户,我得到了以下答案,其中有诀窍:gist.github.com/anonymous/cdac178934b73eae51e0