首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将Kivy ObjectProperty绑定到子小部件似乎不能在根小部件之外工作

将Kivy ObjectProperty绑定到子小部件似乎不能在根小部件之外工作
EN

Stack Overflow用户
提问于 2018-02-24 14:17:57
回答 3查看 1.2K关注 0票数 1

试着遵循这个指南:https://kivy.org/docs/guide/lang.html#accessing-widgets-defined-inside-kv-lang-in-your-python-code

我试图使用id定义访问一个小部件。这在根小部件中工作得很好,但在根小部件之外似乎不起作用。举个例子,下面是代表我的问题的最起码的代码:

GUI.kv文件:

代码语言:javascript
复制
<PlotBox@BoxLayout>:
graph2:graph2_id
BoxLayout:
    id:graph2_id

<RootWidget@BoxLayout>:
    graph:graph_id
    BoxLayout:
        id:graph_id
    PlotBox:

python文件:

代码语言:javascript
复制
#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()

我知道错误:

代码语言:javascript
复制
AttributeError: 'NoneType' object has no attribute 'add_widget'

在RootWidget上,即使我不使用图=ObjectProperty(无),它也能工作。在我的另一个小部件上,似乎没有创建id。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-02-24 16:32:52

根据文档

@字符用于将类名与要子类的类分隔开来。..。

根据得出的结论,在类似于python的.kv中进行继承是一种等效的方法,因此您应该只选择其中一种方式。这将使PlotBox从.py中永远不会被调用。

另一个错误,根据文档,我不知道是否是您的错误,但.kv必须是gui.kv,小写。

执行父构造函数后不直接加载子构造函数,因此将其添加到构造函数中可能会产生问题,在kivy中的一个建议和一个非常常见的做法是使用Clock

以上所述,我已在下列守则中实施:

gui.kv

代码语言:javascript
复制
<PlotBox>:
    graph2:graph2_id
    BoxLayout:
        id:graph2_id

<RootWidget>:
    graph:graph_id
    BoxLayout:
        id:graph_id
    PlotBox:

main.py

代码语言:javascript
复制
#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()

输出:

票数 2
EN

Stack Overflow用户

发布于 2018-02-24 16:37:28

我认为self.graph2只是还没有在__init__中设置-- __init__必须返回才能添加任何子级。

您可以通过执行类似于Clock.schedule_once(function_that_adds_the_button, 0)的操作来解决这一问题。

票数 2
EN

Stack Overflow用户

发布于 2018-02-25 00:53:53

我是在假设您希望在创建应用程序时运行这段代码的假设下工作的,不会晚些时候。

kv。

代码语言:javascript
复制
<PlotBox>:
    BoxLayout:
        id:graph2_id

<RootWidget>:
    BoxLayout:
        id:graph_id
    PlotBox:
        id: plot

py

代码语言:javascript
复制
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来访问:

代码语言:javascript
复制
self.ids.IDGOESHERE

代码语言:javascript
复制
self.children[INDEXOFIDGOESHERE]

至于这一行:

代码语言:javascript
复制
    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方法(至少在我的经验中是这样)。

编辑:

如果要重复访问超长地址,可以将它们封装在函数中以获得它们。

示例:

不太好:

代码语言:javascript
复制
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

更好的是:

代码语言:javascript
复制
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 = newtext
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48963808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档