Python 在单独的.kv文件中为小部件创建属性
我正在学习编写Kivy应用程序。我创建了一个由两个网格布局组成的玩具应用程序。一个包含两个按钮,另一个包含两个标签。任务是在单击按钮时修改标签。当所有的布局都在同一个.kv文件中时,我可以非常简单地做到这一点,只需以标准方式创建id和属性 当我将布局拆分为单独的.kv文件时,我不能做同样的事情。我想这样做,因为我实际工作的项目太复杂,无法包含在单个.kv文件中。这是我的代码: 主要python代码:Python 在单独的.kv文件中为小部件创建属性,python,python-2.7,kivy,Python,Python 2.7,Kivy,我正在学习编写Kivy应用程序。我创建了一个由两个网格布局组成的玩具应用程序。一个包含两个按钮,另一个包含两个标签。任务是在单击按钮时修改标签。当所有的布局都在同一个.kv文件中时,我可以非常简单地做到这一点,只需以标准方式创建id和属性 当我将布局拆分为单独的.kv文件时,我不能做同样的事情。我想这样做,因为我实际工作的项目太复杂,无法包含在单个.kv文件中。这是我的代码: 主要python代码: # filename DynamicApp.py import kivy kivy.requir
# filename DynamicApp.py
import kivy
kivy.require('1.9.0')
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.lang import Builder
Builder.load_file("myfirstgrid.kv")
Builder.load_file("mysecondgrid.kv")
class DynamicWidgets(RelativeLayout):
pass
class DynamicApp(App):
def build(self):
return DynamicWidgets()
if __name__ == "__main__":
DynamicApp().run()
基本kivy文件:
# File name: DynamicApp.kv
#:kivy 1.9.0
<DynamicWidgets>:
MyFirstGrid:
MySecondGrid:
#文件名:dynamiccapp.kv
#:kivy 1.9.0
:
MyFirstGrid:
MySecondGrid:
第一个网格的kivy
# File name: myfirstgrid.kv
#:kivy 1.9.0
<MyFirstGrid@GridLayout>
id: _my_first_grid
rows: 1
cols: 2
Label:
id: _label_1
text: "Hello World"
Label:
id: _label_2
text: "Hello World"
#文件名:myfirstgrid.kv
#:kivy 1.9.0
id:\u我的\u第一个\u网格
行数:1
科尔斯:2
标签:
id:_标签_1
文字:“你好,世界”
标签:
id:_标签_2
文字:“你好,世界”
第二格的Kivy
# File name: myseoncdgrid.kv
#:kivy 1.9.0
#:import mybutton mybutton
<MySecondGrid@GridLayout>
size_hint: 0.25, 0.25
pos_hint: {'center_x': 0.5, 'y' : 0}
rows: 1
cols: 2
MyButton:
text: 'Do it'
label_1: _label_1
MyButton:
text: 'Do it Again'
label_2: _label_2
#文件名:myseoncdgrid.kv
#:kivy 1.9.0
#:导入mybutton mybutton
尺寸提示:0.25,0.25
pos_提示:{'center_x':0.5,'y':0}
行数:1
科尔斯:2
我的按钮:
文字:“做它”
标签\u 1:\u标签\u 1
我的按钮:
文本:“再做一次”
标签2:\u标签2
mybutton.py控制按钮操作,此处不显示,因为我无法在mybutton小部件中创建属性和引用,因为它会给我错误NameError:name'\u label\u 2'未定义
我做了完全相同的策略,但所有的kv都在一个文件中,效果很好
如何在其他.kv文件中创建小部件的引用和属性
我觉得我错过了一些基本的东西
感谢根据上的文档,“id的范围仅限于其声明的规则”。这意味着标签ID在
之外无效。这是有意义的,因为规则可以应用于任何UI树中的小部件,并且它不能提前知道自身之外存在什么或不存在什么
解决问题的方法是使用。您可以将标签文本绑定到StringProperty
,然后当您在代码中更改它时(按下按钮),Kivy将为您更新标签。如果您不能轻松地相互引用小部件,可以将属性放在App
对象上,该对象始终可以在kv中作为App
引用
ex(未经测试):
类动态CAPP(应用程序):
label1=StringProperty(“Hello World”)
label2=StringProperty(“Hello World”)
def生成(自):
返回DynamicWidgets()
...
行数:1
科尔斯:2
标签:
文本:app.label1
标签:
文本:app.label2
...
尺寸提示:0.25,0.25
pos_提示:{'center_x':0.5,'y':0}
行数:1
科尔斯:2
我的按钮:
文字:“做它”
按:app.label1=“做到了”
我的按钮:
文本:“再做一次”
按:app.label2=“再做一次”
所以我想我已经能够回答我自己的问题了。正如我的直觉告诉我的那样,您实际上可以在不同的KV文件中引用ID。您只需确保正确管理引用:
# File name: DynamicApp.kv
#:kivy 1.9.0
<DynamicWidgets>:
MyFirstGrid:
id: _my_first_grid
my_second_grid: _my_second_grid
MySecondGrid:
id: _my_second_grid
my_first_grid: _my_first_grid
谢谢,我想我感到困惑的是,如果所有的.kv都保存在同一个文件中,那么我就可以按照自己的意愿设置属性。毕竟,这些小部件都是
的子部件,以此类推,只是为了方便起见,kv被保存在不同的文件中。你认为用我的方式而不是你的方式做有利弊吗?应用程序实际上是一个玩具,实际上,按钮将以更深刻的方式修改标签或其他小部件(设置可见性等)。ID的范围成为规则本身的原因是规则是一个模块化组件。在您的例子中,您知道这些小部件都是
的子部件,但是Kivy通常不能做出这样的假设,因为规则不知道它将被插入到哪里(它甚至可能没有父项)。就利/弊而言,我认为使用属性更干净一些(代码更少,您不必到处尝试跟踪ID)。它还使您在代码中更容易访问,您只需要访问属性,而不是手动引用小部件树。第二种方法也更为脆弱,如果重新排列UI,所有引用都将中断,需要重新编写。请注意,您不必将所有ID分配给小部件上的属性,有一种简单的方法可以访问它们:
# File name: DynamicApp.kv
#:kivy 1.9.0
<DynamicWidgets>:
MyFirstGrid:
id: _my_first_grid
my_second_grid: _my_second_grid
MySecondGrid:
id: _my_second_grid
my_first_grid: _my_first_grid
# File name: myfirstgrid.kv
#:kivy 1.9.0
<MyFirstGrid@GridLayout>
id: _my_first_grid
label_1: _label_1
label_2: _label_2
rows: 1
cols: 2
Label:
id: _label_1
text: "Hello World"
Label:
id: _label_2
text: "Hello World"
# File name: myseoncdgrid.kv
#:kivy 1.9.0
#:import mybutton mybutton
<MySecondGrid@GridLayout>
size_hint: 0.25, 0.25
pos_hint: {'center_x': 0.5, 'y' : 0}
rows: 1
cols: 2
MyButton:
text: 'Do it'
on_press: self.onClick1(*args)
MyButton:
text: 'Do it Again'
on_press: self.onClick2(*args)
#file button.py
from kivy.uix.button import Button
class MyButton(Button):
def onClick1(self, instance):
print 'OK'
mfg = self.parent.my_first_grid
mfg.label_1.text = "Hello Universe"
return True
def onClick2(self, instance):
mfg = self.parent.my_first_grid
mfg.label_2.text = "Hello Galaxy"
return True