试着遵循这个指南:https://kivy.org/docs/guide/lang.html#accessing-widgets-defined-inside-kv-lang-in-your-python-code
我试图使用id定义访问一个小部件。这在根小部件中工作得很好,但在根小部件之外似乎不起作用。举个例子,下面是代表我的问题的最起码的代码:
GUI.kv文件:
<PlotBox@BoxLayout>:
graph2:graph2_id
BoxLayout:
id:graph2_id
<RootWidget@BoxLayout>:
graph:graph_id
BoxLayout:
id:graph_id
PlotBox:python文件:
#kivy imports
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
class PlotBox(BoxLayout):
graph2 = ObjectProperty(None)
def __init__(self,**kwargs):
super(PlotBox,self).__init__(**kwargs)
self.graph2.add_widget(Button(text="This doesn't work"))
class RootWidget(BoxLayout):
graph = ObjectProperty(None)
def __init__(self,**kwargs):
super(RootWidget,self).__init__(**kwargs)
self.graph.add_widget(Button(text='This works'))
class GUIApp(App):
def build(self):
self.root = RootWidget()
return self.root
if __name__ == "__main__":
GUIApp().run()我知道错误:
AttributeError: 'NoneType' object has no attribute 'add_widget'在RootWidget上,即使我不使用图=ObjectProperty(无),它也能工作。在我的另一个小部件上,似乎没有创建id。
发布于 2018-02-24 16:32:52
根据文档
@字符用于将类名与要子类的类分隔开来。..。
根据得出的结论,在类似于python的.kv中进行继承是一种等效的方法,因此您应该只选择其中一种方式。这将使PlotBox从.py中永远不会被调用。
另一个错误,根据文档,我不知道是否是您的错误,但.kv必须是gui.kv,小写。
执行父构造函数后不直接加载子构造函数,因此将其添加到构造函数中可能会产生问题,在kivy中的一个建议和一个非常常见的做法是使用Clock。
以上所述,我已在下列守则中实施:
gui.kv
<PlotBox>:
graph2:graph2_id
BoxLayout:
id:graph2_id
<RootWidget>:
graph:graph_id
BoxLayout:
id:graph_id
PlotBox:main.py
#kivy imports
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
from kivy.clock import Clock
class PlotBox(BoxLayout):
graph2 = ObjectProperty(None)
def __init__(self,**kwargs):
super(PlotBox,self).__init__(**kwargs)
Clock.schedule_once(lambda dt: self.graph2.add_widget(Button(text="This now works")))
class RootWidget(BoxLayout):
graph = ObjectProperty(None)
def __init__(self,**kwargs):
super(RootWidget,self).__init__(**kwargs)
self.graph.add_widget(Button(text='This works'))
class GUIApp(App):
def build(self):
root = RootWidget()
return root
if __name__ == "__main__":
GUIApp().run()输出:

发布于 2018-02-24 16:37:28
我认为self.graph2只是还没有在__init__中设置-- __init__必须返回才能添加任何子级。
您可以通过执行类似于Clock.schedule_once(function_that_adds_the_button, 0)的操作来解决这一问题。
发布于 2018-02-25 00:53:53
我是在假设您希望在创建应用程序时运行这段代码的假设下工作的,不会晚些时候。
kv。
<PlotBox>:
BoxLayout:
id:graph2_id
<RootWidget>:
BoxLayout:
id:graph_id
PlotBox:
id: plotpy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
class PlotBox(BoxLayout):
pass
class RootWidget(BoxLayout):
pass
class GUIApp(App):
def build(self):
root = RootWidget()
# We can add things to the Root during build before we return it
# This means we add this information before the user sees anything
root.ids.graph_id.add_widget(Button(text='This works'))
# See end of answer for more about this
root.ids.plot.ids.graph2_id.add_widget(Button(text='This works!'))
return root
if __name__ == "__main__":
GUIApp().run()首先,您不需要对象属性来访问it,您可以通过it或子it来访问:
self.ids.IDGOESHERE或
self.children[INDEXOFIDGOESHERE]至于这一行:
root.ids.plot.ids.graph2_id.add_widget(Button(text='This works!'))Root有一个plotbox类的实例,其id为“plot”。绘图类(因此,所有情节类的实例)都有一个BoxLayout实例,其中包含我们可以访问的id图。
所以我们要做的是:
根->图-> Graph2
如果我们要添加另一个带有id‘Graph2 _ graph2’的plotbox,那么我们可以按照以前的方法获得一个plotbox,也可以得到一个不同的graph2,因为它属于plotbox的不同实例。
我们以前做的事
根->图-> Graph2
一个不同的id,因此是不同的小部件。
根-> big_plot -> Graph2
除非调用super,否则很少需要在Kivy Widget类中使用init方法(至少在我的经验中是这样)。
编辑:
如果要重复访问超长地址,可以将它们封装在函数中以获得它们。
示例:
不太好:
def func_one(self):
newtext = 'new'
self.ids.IDONE.ids.IDTWO.ids.IDTHREE.ids.IDFOUR.text = newtext
def func_two(self):
newtext = 'newtwo'
self.ids.IDONE.ids.IDTWO.ids.IDTHREE.ids.IDFOUR.text = newtext
def func_three(self):
newtext = 'newthree'
self.ids.IDSONE.Ids.IDTWO.ids.IDTHREE.ids.IDFOUR.text = newtext更好的是:
def long_address(self):
return self.ids.IDSONE.ids.IDSTWO.ids.IDTHREE.ids.IDFOUR
def func_one(self):
newtext = 'new'
self.long_address().text = newtext
def func_two(self):
newtext = 'newtwo'
self.long_address().text = newtext
def func_three(self):
newtext = 'newthree'
self.long_address().text = newtexthttps://stackoverflow.com/questions/48963808
复制相似问题