无法在Kivy中引用小部件ID

时间:2018-02-19 17:32:37

标签: python kivy kivy-language

Kivy很新,并试图动态添加小部件,但尽管我遵循了所有的例子,但我无法让我的工作。

我的.kv文件是......

ScreenManager:
    MainScreen:
    LoginScreen:

<MainScreen>:
   name: 'MainScreen'
   id: ms

   BoxLayout:
        id: rc_display
        orientation: "vertical"
        padding: 10
        spacing: 10

        Label:
            id: ms_label1
            text: 'Oh Hell Yeah'

<LoginScreen>:
    name: 'LoginScreen'
    id: ls

    Button:
        on_release: app.root.current
        text: 'Click to Login'
        font_size: 20

我的python代码是......

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
import requests

class MainScreen(Screen):

   def on_pre_enter(self, *args):

        show_view = self.ids.rc_display # error here
        show_view.clear_widgets()
        buttons = BoxLayout(orientation = 'vertical')
        pr = requests.get('http://127.0.0.1:5000/stageplanning/api/v1.0/shows')
        for show in pr.json():
            buttons.add_widget(Button(text = show['show_title']))

        show_view.add_widgets(buttons)    

class LoginScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

class StagePlanningApp(App):
    def build(self):

        sm = Builder.load_file('StagePlanning.kv')
        # sm.add_widget(MainScreen())
        # sm.add_widget(LoginScreen())
        return sm

sp_app = StagePlanningApp()
sp_app.run()

当我运行以上内容时,我收到以下错误...

File "*pathtoFile*/StagePlanning.py", line 12, in on_pre_enter
 show_view = self.ids.rc_display
File "kivy\properties.pyx", line 839, in kivy.properties.ObservableDict.__getattr__ (kivy\properties.c:12654)
AttributeError: 'super' object has no attribute '__getattr__'

如果我将小部件直接添加到它们显示的Screen对象中,但它们彼此重叠。只有当我尝试引用id时才会出现错误。

我甚至在控制台上打印了ID列表,它们按预期存在。

1 个答案:

答案 0 :(得分:0)

问题的原因是on_pre_enter事件在添加BoxLayout之前完成,因此它不存在,可能的解决方案是使用Clock

class MainScreen(Screen):
    def __init__(self, *args, **kwargs):
        Screen.__init__(self, *args, **kwargs)
        Clock.schedule_once(self.finished_init)

    def finished_init(self, *args):
        show_view = self.ids.rc_display # error here
        show_view.clear_widgets()
        buttons = BoxLayout(orientation = 'vertical')
        pr = requests.get('http://127.0.0.1:5000/stageplanning/api/v1.0/shows')
        for show in pr.json():
            buttons.add_widget(Button(text = show['show_title']))

        show_view.add_widget(buttons) 

另一个选择是在BoxLayout构造函数中定义它:

<强> *。PY

class MainBoxLayout(BoxLayout):
    def __init__(self, *args, **kwargs):
        BoxLayout.__init__(self, *args, **kwargs)
        self.clear_widgets()
        buttons = BoxLayout(orientation = 'vertical')
        pr = requests.get('http://127.0.0.1:5000/stageplanning/api/v1.0/shows')
        for show in pr.json():
            buttons.add_widget(Button(text = show['show_title']))
        self.add_widget(buttons) 

<强> *。KV

ScreenManager:
    MainScreen:
    LoginScreen:

<MainScreen>:
    name: 'MainScreen'
    id: ms

    MainBoxLayout:
        id: rc_display
        orientation: "vertical"
        padding: 10
        spacing: 10

<LoginScreen>:
    name: 'LoginScreen'
    id: ls

    Button:
        on_release: app.root.current
        text: 'Click to Login'
        font_size: 20