【问题标题】:Can't change an InputBox content in KivyMD无法更改 KivyMD 中的 InputBox 内容
【发布时间】:2021-12-27 11:59:17
【问题描述】:

我正在尝试制作一个启动日期选择器的 InputBox,当您选择一个日期时,它会出现在框中。所以我这样绑起来:

from kivymd.app import MDApp
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.menu import MDDropdownMenu
from kivy.metrics import dp
from kivymd.uix.snackbar import Snackbar
from kivymd.uix.dialog import MDDialog
from kivymd.uix.picker import MDDatePicker


class MainScreen(Screen):
    pass

class Predef(Screen):
    pass

class WindowManager(ScreenManager):
    pass



class MyApp(MDApp):
    def build(self):
        self.birthday = ''
        
        kv = Builder.load_file('file.kv')
        return kv
    

    def on_save(self, instance, value, date_range):
    
        print(value)
        self.birthday = value
        self.root.ids.input_box_date.text = self.birthday


    def on_cancel(self, instance, value):
        print("cancel")
    def date(self):
            date_dialog = MDDatePicker(
                title='Birthday',
                title_input= 'Birthday'
                )
            date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
            date_dialog.open()
        
    
if __name__ == '__main__':
    MyApp().run()

这是kv文件中的代码:

WindowManager:
    MainScreen:
    Predef:
<MainScreen>:
    name: "main"
    MDBoxLayout:
        orientation: 'vertical'
        size: root.width, root.height
        MDToolbar:
            title: "App"
            left_action_items: [["menu", lambda x: side_bar.set_state("open")]]
        Label:
            text: 'Image'
            color: (0, 0, 0, 1)

        MDBottomAppBar:
            MDToolbar:
                icon: "botão.png"
                type: "bottom"
    MDNavigationDrawer:
        id: side_bar
        BoxLayout:
            orientation: 'vertical'
            padding: '16dp'
            Label:
                color: (0, 0, 0, 1)
                font_size: 35
                text: 'Settings      '
                size_hint_y: None
                height: self.texture_size[1]
                pos_hint: {'y': 0, 'left': 1}
            ScrollView:
                MDList:
                    OneLineListItem:
                        text: 'Predefitions'
                        on_release:
                            side_bar.set_state("close")
                            app.root.current = 'Predef'
                            root.manager.transition.direction = "up"
<Predef>:
    name: 'Predef'
    MDBoxLayout:
        orientation: 'vertical'
        size: root.height, root.width
        MDToolbar:
            title: "Predefinitions"
            left_action_items: [["menu", lambda x: bar.set_state("open")]]
            pos_hint: {'x': 0, 'top': 1}
        Label:
            color: (0, 0, 0, 1)
            text: 'Birthday'
        MDTextFieldRound:
            id: input_box_date    
            hint_text: "Birthday"
            text: app.birthday
            size_hint_x : 0.5
            pos_hint: {'center_x' : 0.5}
            on_focus: app.date()
        Label:
            text: ''
    MDNavigationDrawer:
        id: bar
        BoxLayout:
            orientation: 'vertical'
            padding: '16dp'
            Label:
                color: (0, 0, 0, 1)
                font_size: 35
                text: 'Settings      '
                size_hint_y: None
                height: self.texture_size[1]
                pos_hint: {'y': 0, 'left': 1}
            ScrollView:
                MDList:
                    OneLineListItem:
                        text: 'Main Screen'
                        on_release:
                            bar.set_state("close")
                            app.root.current = 'main'
                            root.manager.transition.direction = "up"     

当它启动时,一切正常。 InputBox 按我的预期开始为空,但是当我单击“确定”按钮时出现此错误:

'''
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "kivy\properties.pyx", line 861, in kivy.properties.ObservableDict.__getattr__
 KeyError: 'input_box_date'
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 112, in <module>
     MyApp().run()
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\app.py", line 950, in run
     runTouchApp()
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 347, in mainloop
     self.idle()
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 391, in idle
     self.dispatch_input()
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\base.py", line 308, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\behaviors\ripple_behavior.py", line 296, in on_touch_up
     return super().on_touch_up(touch)
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivymd\uix\button.py", line 981, in on_touch_up
     return super().on_touch_up(touch)
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "<string>", line 213, in <module>
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1172, in kivy._event.EventObservers._dispatch
   File "C:\Users\MYUSERNAME\AppData\Local\Programs\Python\Python39\program.py", line 77, in on_save
     self.root.ids.input_box_date.text = self.birthday
   File "kivy\properties.pyx", line 864, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'
'''

我不知道为什么会出现此错误。我尝试用self.root.ids.input_box_date.text = "string" 替换self.root.ids.input_box_date.text = self.birthday,但没有任何变化。我该怎么办?

【问题讨论】:

    标签: python kivy kivymd


    【解决方案1】:

    TL;DR: 屏幕位于 rootids 之间,日期选择器返回 datetime.date,需要将其转换为字符串 用于文本字段:self.root.get_screen('Predef').ids.input_box_datex.text = str(value).

    根和孩子

    在您的 KV 文件中,您在 root WindowManager:

    中定义了两个屏幕
    WindowManager:
        MainScreen:
        Predef:
    

    在您的 Python 脚本中,使用 self.root 访问此 root。 所以print(self.root) 会给出类似的输出:

    ma​​in.WindowManager 对象位于 0x7fa580c48f28>

    在此根中,screens 可以使用self.root.screens 作为索引列表找到。打印将输出:

    [, ]

    按索引访问屏幕,例如第一次使用screens[0] 或对于给定id 的特定屏幕使用get_screen(id)

    与所有 Kivy 小部件一样,屏幕上都有 children: 所有这些子小部件都有ids,可以使用self.root.get_screen('Predef').ids 将其列为dict:

    {'input_box_date': >, 'bar': >}

    并通过ids['input_box_date']ids.input_box_date 访问。

    另见:

    在文本字段上设置日期

    由于文本字段是在屏幕内定义的,ID 为 'Predef',因此请使用以下任一选项:

    • self.root.get_screen('Predef').ids['input_box_date']
    • self.root.get_screen('Predef').ids.input_box_date

    但是,日期选择器返回一个 datetime 类型的值,因此您需要使用 str() 将其转换为字符串:

    def on_save(self, instance, value, date_range):
        print("value/type:", value, type(value))
        self.birthday = value  # the instance variable becomes of type date
        self.root.get_screen('Predef').ids.input_box_date.text = str(date)  # convert to string
    

    另见:

    访问树中的相关元素

    print(self.root)
    print(self.root.screens)
    print(self.root.screens[1].ids)
    print(self.root.screens[1].ids.input_box_date)
    print(self.root.get_screen('Predef').children)
    print(self.root.get_screen('Predef').ids['input_box_date'])
    print(self.root.get_screen('Predef').ids.input_box_date)
    

    见:

    【讨论】:

      【解决方案2】:

      错误消息显示KeyError: 'input_box_date'。这意味着您使用的ids 中没有input_box_date 键。该键在&lt;Predef&gt;: 规则中定义,因此id 将位于Predef 实例的ids 中。解决方法是使用Predef 实例访问id。尝试替换:

      self.root.ids.input_box_date.text = self.birthday
      

      与:

      self.root.get_screen('Predef').ids.input_box_date.text = self.birthday
      

      【讨论】:

      • 谢谢,解决了我的问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 2012-07-14
      • 2023-04-03
      • 2019-01-20
      • 2016-10-30
      相关资源
      最近更新 更多