好的,我尝试在Kivy制作我的第一个应用程序,并且我的Root Widget的多个实例出现问题。
我需要在运行时向我的应用添加小部件。 (显示电子表格)
但是由于Root Widget的多个实例,我无法使用kivy id查找对象访问小部件。
https://kivy.org/docs/guide/lang.html
我制作了三个按钮以在控制台中显示问题 按钮-1 - , - 2和-3 -
请解释为什么有多个实例以及我如何阻止它,因此代码可以正常工作。
感谢您的帮助!
档案 - > Match.py
#!python
from __future__ import print_function
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
import gc
class my_gc():
def search_g(self):
for obj in gc.get_objects():
if isinstance(obj, Root):
try:
print(obj.ids)
except:
print('fail')
#Root Widget
class Root(BoxLayout):
sm = ObjectProperty(None)
sc0 = ObjectProperty(None)
sc1 = ObjectProperty(None)
sc2 = ObjectProperty(None)
sc3 = ObjectProperty(None)
mylbl0 = StringProperty('screen 0')
mylbl1 = StringProperty('screen 1')
mylbl2 = StringProperty('screen 2')
mylbl3 = StringProperty('screen 3')
def find_ids(self):
print(self.ids)
class Screen_Manager(ScreenManager):
pass
class Screen_0(Screen):
pass
class Screen_1(Screen):
pass
class Screen_2(Screen):
pass
class Screen_3(Screen):
pass
class Match(App):
rootwidget = Root()
sm = Screen_Manager()
gc = my_gc()
def build(self):
pass
Match().run()
档案 - > Match.kv
#Root Widget (BoxLayout)
Root:
sm: sm
sc1: sc0
sc1: sc1
sc1: sc2
sc1: sc3
BoxLayout:
spacing: '20dp'
orientation: 'vertical'
Screen_Manager:
id: sm
Screen_0:
id: sc0
name: 'sc0'
manager: 'sm'
BoxLayout:
id: box_0-0
Label:
id: lbl_0
text: app.rootwidget.mylbl0
Label:
id: lbl_0-1
text: root.mylbl0
Screen_1:
id: sc1
name: 'sc1'
manager: 'sm'
Label:
id: lbl1
text: root.mylbl1
Screen_2:
id: sc2
name: 'sc2'
manager: 'sm'
Label:
id: lbl2
text: root.mylbl2
Screen_3:
id: sc3
name: 'sc3'
manager: 'sm'
Label:
id: lbl3
text: root.mylbl3
#Tab-Buttons
BoxLayout:
size_hint: 1 , None
height: '60dp'
orientation: 'horizontal'
Button:
text: '-0-'
on_press: root.sm.current = sc0.name
Button:
text: '-1-'
on_press: root.sm.current = sc1.name
Button:
text: '-2-'
on_press: root.sm.current = sc2.name
Button:
text: '-3-'
on_press: root.sm.current = sc3.name
Button:
text: '<'
size_hint: None , 1
width: '60dp'
on_press: root.sm.current = root.sm.previous()
Button:
text: '>'
size_hint: None , 1
width: '60dp'
on_press: root.sm.current = root.sm.next()
Button:
text: '-b1-'
size_hint: None , 1
width: '60dp'
#on_press: root.search_g() #<-- doesn't work
on_press: app.gc.search_g() #<-- works
Button:
text: '-b2-'
size_hint: None , 1
width: '60dp'
on_press: root.find_ids() #<-- doesn't work
on_press: app.rootwidget.find_ids() #<-- works
Button:
text: '-b3-'
size_hint: None , 1
width: '60dp'
on_press: print(root.mylbl1) #<-- works
on_press: print(app.rootwidget.mylbl1) #<-- works
答案 0 :(得分:0)
根据您的代码,您没有根小部件的多个实例。您的根小部件是 Root: ,根据kv文件, match.kv 。
它不起作用,因为您的root(BoxLayout)类没有 search_g() 方法。
当我评论 app.rootwidget.find_ids 时,对 root.find_ids 的调用有效,即它打印了ids。关键字 root 仅在规则定义中可用,并表示规则的根小部件(规则的第一个实例)。解析kv文件后,kivy会收集所有标记为id的小部件,并将它们放在 self.ids 字典类型属性中。
它工作但没有id,因为它引用了发起的对象类Root中的方法find_ids。 rootwidget 只是一个名称变量,它与 Root:
从附带的屏幕截图中,您会注意到root.find_ids和app.rootwidget.find_ids的对象位置不同。
要在应用运行时动态添加小部件,您必须执行以下操作。有关示例,请参阅Kivy/python : when i click row then it shows error IndexError: list index out of range
上的其他帖子添加导入语句如下:
来自kivy.properties导入ObjectProperty
声明变量(例如容器)或ObjectProperty类型,例如在类Root
中类Root(BoxLayout): container = ObjectProperty(无)
在添加
动态添加小部件。
将ObjectProperty连接到id
根: 容器:容器 ... #动态添加小部件的容器 BoxLayout的: id:container
解决方案是声明一个ObjectProperty,rootwidget如下:
class Match(App):
rootwidget = ObjectProperty(None)
title = "Solution App"
gc = my_gc()
def build(self):
self.rootwidget = Root()
return self.rootwidget
#!python
from __future__ import print_function
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
import gc
class my_gc():
def search_g(self):
print("my_gc.search_g called")
for obj in gc.get_objects():
if isinstance(obj, Root):
try:
print("obj={0}, ids={1}".format(obj, obj.ids))
for key, value in obj.ids.items():
print(" key={0}, value={1}".format(key, value))
except:
print('fail')
# Root Widget
class Root(BoxLayout):
sm = ObjectProperty(None)
sc0 = ObjectProperty(None)
sc1 = ObjectProperty(None)
sc2 = ObjectProperty(None)
sc3 = ObjectProperty(None)
mylbl0 = StringProperty('screen 0')
mylbl1 = StringProperty('screen 1')
mylbl2 = StringProperty('screen 2')
mylbl3 = StringProperty('screen 3')
def find_ids(self):
print("Root.find_ids called")
print("self={0}, self.ids={1}".format(self, self.ids))
for key, value in self.ids.items():
print(" key={0}, value={1}".format(key, value))
class Screen_Manager(ScreenManager):
pass
class Screen_0(Screen):
pass
class Screen_1(Screen):
pass
class Screen_2(Screen):
pass
class Screen_3(Screen):
pass
class Match(App):
rootwidget = ObjectProperty(None)
title = "Solution App"
gc = my_gc()
def build(self):
self.rootwidget = Root()
return self.rootwidget
if __name__ == "__main__":
Match().run()
#Root Widget (BoxLayout)
<Root>:
sm: sm
sc1: sc0
sc1: sc1
sc1: sc2
sc1: sc3
BoxLayout:
spacing: '20dp'
orientation: 'vertical'
Screen_Manager:
id: sm
Screen_0:
id: sc0
name: 'sc0'
manager: 'sm'
BoxLayout:
id: box_0-0
Label:
id: lbl_0
text: root.mylbl0
Label:
id: lbl_0-1
text: root.mylbl0
Screen_1:
id: sc1
name: 'sc1'
manager: 'sm'
Label:
id: lbl1
text: root.mylbl1
Screen_2:
id: sc2
name: 'sc2'
manager: 'sm'
Label:
id: lbl2
text: root.mylbl2
Screen_3:
id: sc3
name: 'sc3'
manager: 'sm'
Label:
id: lbl3
text: root.mylbl3
#Tab-Buttons
BoxLayout:
id: secondBoxLayout
size_hint: 1 , None
height: '60dp'
orientation: 'horizontal'
Button:
text: '-0-'
on_press: root.sm.current = sc0.name
Button:
text: '-1-'
on_press: root.sm.current = sc1.name
Button:
text: '-2-'
on_press: root.sm.current = sc2.name
Button:
text: '-3-'
on_press: root.sm.current = sc3.name
Button:
text: '<'
size_hint: None , 1
width: '60dp'
on_press: root.sm.current = root.sm.previous()
Button:
text: '>'
size_hint: None , 1
width: '60dp'
on_press: root.sm.current = root.sm.next()
Button:
text: '-b1-'
size_hint: None , 1
width: '60dp'
on_press:
print("\non_press: {}".format(self.text))
# root.search_g() #<-- doesn't work
print(" app.gc_search_g()")
app.gc.search_g() #<-- works
Button:
text: '-b2-'
size_hint: None , 1
width: '60dp'
on_press:
print("\non_press: {}".format(self.text))
print(" root.find_ids()")
root.find_ids() #<-- works
print("\n app.root.find_ids()")
app.rootwidget.find_ids() #<-- works
Button:
text: '-b3-'
size_hint: None , 1
width: '60dp'
on_press:
print("\non_press: {}".format(self.text))
print(root.mylbl1) #<-- works
print(app.rootwidget.mylbl1) #<-- works