无法通过ID获取Kivy小部件

时间:2018-06-27 09:05:21

标签: python kivy

我这样做是为了显示我想要的东西,但未能完成。当我尝试访问小部件时,收到消息:“ AttributeError:'super'对象没有属性' getattr '”。

请有人说明如何使用小部件id:s,以便您可以使用python代码从任何地方访问它们,我敢肯定我做的是根本上错误的事情。

from kivy.app import App
from kivy.uix.screenmanager import Screen, ScreenManager, SlideTransition
from kivy.lang.builder import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
import random


Builder.load_string('''

<Manager>:
    id: screen_manager
    SettingScreen:
        id: settings
        name: 'settings'
        manager: 'screen_manager'

    MainScreen:
        id: mainscreen
        name: 'mainscreen'
        manager: 'screen_manager'

    ThirdScreen:
        id: thirdscreen
        name: 'thirdscreen'
        manager: 'screen_manager'

<SettingScreen>:

    BoxLayout:
        id: settingbox
        orientation: "vertical"

        TextInput:
            id: getthis
            text: "this is the data"
            font_size: 40
            size_hint: 1,0.1

        Button:
            text: "NEXT SCREEN"
            font_size: 40
            size_hint: 1,0.1
            on_release:
                app.root.current = "mainscreen"                            
                app.root.transition.direction="left"                                

<MainScreen>:

    BoxLayout:
        orientation: 'vertical'

        Label:
            id: changethis
            text: "to be changed"

        Button:
            text: "Push this to make above into the text from TextInput on last screen"
            on_release:
                app.root.ids.changethis.text = app.root.ids.getthis.text #<<<<<
        Button:
            text: "Go to third Screen"
            on_release:
                app.root.current = "thirdscreen"                            
                app.root.transition.direction="left"

<ThirdScreen>
    put_label_here: put_label_here
    BoxLayout:
        orientation: 'horizontal'

        Button:
            text: 'Make make label'
            on_release:
                self.parent.parent.makelabel()

        BoxLayout:
            orientation: 'vertical'
            id: put_label_here
''')

class MainScreen(Screen):   
    def __init__(self, **kwargs):
        Screen.__init__(self, **kwargs)

class SettingScreen(Screen):
    def __init__(self, **kwargs):
        super(SettingScreen, self).__init__(**kwargs)

class ThirdScreen(Screen):
    def __init__(self, **kwargs):
        super(ThirdScreen, self).__init__(**kwargs)

    def makelabel(self): #this should make a Label with text from TextInput on SettingScreen
        print('Runs function makelabel')
        thelabel=Label(text=self.parent.settings.settingbox.getthis.text)
        self.put_label_here.add_widget(thelabel)

class Manager(ScreenManager):
    pass

sm = ScreenManager(transition=SlideTransition())
sm.add_widget(MainScreen(name='mainscreen'))
sm.add_widget(SettingScreen(name='settings'))
sm.add_widget(SettingScreen(name='thirdscreen'))

class testApp(App):

    def build(self):
        return Manager()

if __name__ == "__main__":
    testApp().run()

1 个答案:

答案 0 :(得分:0)

好吧,我可以为您解决此问题,但是老实说,我认为您没有正确使用kv模板。但是还是可以的。

一个新模板本身就是一个规则,它有自己的根,因此作为回报,应用程序根(app.root)将无法直接访问在他们自己的模板中定义的子代ID。因此,您必须到达其直接子节点,该子节点将创建一个包含要访问的子节点的模板,然后通过其ID到达该子节点。

例如,在您的kv代码中,您需要将第63行(kv)更改为:

app.root.ids.changethis.text = app.root.ids.getthis.text

收件人:

app.root.ids.mainscreen.ids.changethis.text = app.root.ids.settings.ids.getthis.text

和第99行(python)来自:

thelabel=Label(text=self.parent.settings.settingbox.getthis.text)

收件人:

thelabel=Label(text=self.parent.ids.settings.ids.getthis.text)

为什么root(或任何父窗口小部件)不应访问在单独模板中定义的ID? 模板或动态类是为了可重用而设计的,就像任何非静态类一样。

请考虑以下情形:

BoxLayout:
    CustomWidget:
        id: wdg1
    CustomWidget:
        id: wdg2
    Button:
        text: 'change text of first label'
        on_press: root.ids.lbl.text = 'new text'

<CustomWidget@Widget>:
    Label:
        text: 'some text'
        id: lbl

现在,根窗口小部件有两个CustomWidget实例作为子项,因此,两个子标签的ID为'lbl'。如果根直接调用lbl,应该调用哪一个?

要处理此问题,可以从其直接模板实例调用lbl。因此:第一个小部件内的标签为root.ids.wdg1.ids.lbl.text,第二个小部件内的标签为root.ids.wdg2.ids.lbl.text。