Не удается получить Kivy виджетов по идентификаторам - PullRequest
0 голосов
/ 27 июня 2018

Я сделал это, чтобы показать, что я хочу, но не могу сделать. Я получаю сообщение: «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 голосов
/ 27 июня 2018

Что ж, я могу исправить это для вас, но, честно говоря, я не думаю, что вы правильно используете шаблоны kv. Но это все равно будет работать.

Новый шаблон сам по себе является правилом, у него есть собственный корень, поэтому взамен корень приложения (app.root) не будет иметь прямого доступа к идентификаторам детей, определенным в их собственных шаблонах. Таким образом, вам нужно связаться с его прямым потомком, который создаст шаблон, содержащий дочерний элемент, к которому вы хотите получить доступ, и вы достигнете этого потомка по его идентификатору.

Например, в вашем коде 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)

Почему рут (или любой родительский виджет) не должен обращаться к идентификаторам, определенным в отдельных шаблонах? Шаблоны или динамические классы созданы для повторного использования, как и любой нестатический класс.

Рассмотрим следующий сценарий:

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 в качестве дочерних элементов, таким образом, два дочерних ярлыка имеют идентификатор «lbl». Какой из них должен быть вызван, если корень вызвал lbl напрямую?

Чтобы справиться с этим, вы можете вызвать lbl из его прямого экземпляра шаблона. Таким образом: root.ids.wdg1.ids.lbl.text для метки внутри первого виджета или root.ids.wdg2.ids.lbl.text для метки внутри второго виджета.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...