AttributeError: 'NoneType' object has no attribute 'ids', in kivymd
AttributeError: 'NoneType' object has no attribute 'ids', in kivymd
我在 kivymd 中创建了一个简单的 MDfieldwidget 我试图引用文本但是我得到了一个 AttributeError: 'NoneType' object has no attribute 'ids',
这是我的 main.py 文件(提前感谢您的帮助)
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
class LoginScreen(Screen):
pass
class SecondScreen(Screen):
pass
class LoginApp(MDApp):
def build(self):
users_name = self.root.ids.users_name
my_label = self.root.ids.my_label
my_label.text = users_name.text
sm = ScreenManager()
sm.add_widget(LoginScreen(name='Screen1'))
sm.add_widget(SecondScreen(name='Screen2'))
return sm
LoginApp().run()
这是我的 .kv 文件
<LoginScreen>
MDScreen:
name: 'Screen1'
md_bg_color: (23/255, 31/255, 40/255, 1)
MDCard:
size_hint: None, None
size: 320, 400
pos_hint: {"center_x": .5, "center_y": .5}
orientation: 'vertical'
padding: '8dp'
md_bg_color: (23/255, 31/255, 47/255, 1)
elevation: 10
spacing: 10
MDLabel:
text: 'LOGIN'
font_style: 'Button'
font_size: 45
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
theme_text_color: 'Custom'
text_color: (1, 1, 1, 1)
padding_y: 15
MDTextFieldRound:
hint_text: 'enter username'
icon_right: 'account'
color_active: 1, 1, 1, 1
pos_hint: {"center_x":.5}
size_hint_x: None
width: 220
font_size: 16
# MDSeparator:
# height: "1dp"
MDTextFieldRound:
hint_text: 'enter password'
icon_right: 'eye-off'
color_active: 1, 1, 1, 1
size_hint_x: None
width: 210
font_size: 15
pos_hint: {"center_x": .5}
password: True
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
MDRectangleFlatButton:
text: 'LOGIN'
pos_hint: {'center_x': .5}
size_hint_x: None
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'left'
root.manager.current = 'Screen2'
Widget:
pos_hint_y: None
height: 30
<SecondScreen>
MDScreen:
md_bg_color: (23/255, 31/255, 40/255, 1)
name: 'Screen2'
MDCard:
md_bg_color: (23/255, 31/255, 47/255, 1)
padding: 10
elevation: 10
orientation: 'vertical'
spacing: 25
pos_hint: {'center_x': .5, "center_y": .5}
size_hint: None, None
size: 340, 400
MDTextButton:
text: '< Back'
padding_x: 0
custom_color: (244/255, 246/255, 214/255, 1)
pos_hint: {"center_y": .1}
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'right'
root.manager.current = 'Screen1'
MDLabel:
id: my_label
text: f'Hello {my_label.text}'
# halign: 'center'
pos_hint: {'center_x': .5}
size_hint_y: None
font_style: 'Body1'
theme_text_color: 'Custom'
text_color: (1, 1, 1, 1)
font_size: 20
height: self.texture_size[1]
padding_y: 15
Widget:
height: 10
您的代码有几个问题:
- 您正试图在用户有机会将文本输入
MDTextField
之前将文本从 MDTextField
复制到 MDLabel
。此外,ids
尚未在 build()
方法中分配。
- 您正在尝试使用
self.root
访问 ids
,即 ScreenManager
,但 ids
是在 LoginScreen
和 SecondScreen
。见 documentation.
您可以通过在用户输入名称时复制名称并正确使用 ids
来解决这些问题。在你的kv
中,使用text
属性触发复制:
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
on_text: app.set_user_name(self.text)
然后将set_user_name()
方法添加到App
:
def set_user_name(self, name):
my_label = self.root.get_screen('Screen2').ids.my_label
my_label.text = name
当然,从 build()
中删除这些行:
users_name = self.root.ids.users_name
my_label = self.root.ids.my_label
my_label.text = users_name.text
另一种方法,如果您不想擦除 MDLabel
中已有的文本,则使用 MDRectangleFlatButton
作为触发器。在这种情况下,MDTextField 的 kv
变为:
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
这是你的原始代码。将 set_user_name()
方法的触发器添加到 Button
:
MDRectangleFlatButton:
text: 'LOGIN'
pos_hint: {'center_x': .5}
size_hint_x: None
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'left'
root.manager.current = 'Screen2'
app.set_user_name(users_name.text) # trigger name copy
并且set_user_name()
方法必须调整为:
def set_user_name(self, name):
my_label = self.root.get_screen('Screen2').ids.my_label
my_label.text += name # append name rather than over-write
我在 kivymd 中创建了一个简单的 MDfieldwidget 我试图引用文本但是我得到了一个 AttributeError: 'NoneType' object has no attribute 'ids', 这是我的 main.py 文件(提前感谢您的帮助)
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
class LoginScreen(Screen):
pass
class SecondScreen(Screen):
pass
class LoginApp(MDApp):
def build(self):
users_name = self.root.ids.users_name
my_label = self.root.ids.my_label
my_label.text = users_name.text
sm = ScreenManager()
sm.add_widget(LoginScreen(name='Screen1'))
sm.add_widget(SecondScreen(name='Screen2'))
return sm
LoginApp().run()
这是我的 .kv 文件
<LoginScreen>
MDScreen:
name: 'Screen1'
md_bg_color: (23/255, 31/255, 40/255, 1)
MDCard:
size_hint: None, None
size: 320, 400
pos_hint: {"center_x": .5, "center_y": .5}
orientation: 'vertical'
padding: '8dp'
md_bg_color: (23/255, 31/255, 47/255, 1)
elevation: 10
spacing: 10
MDLabel:
text: 'LOGIN'
font_style: 'Button'
font_size: 45
halign: 'center'
size_hint_y: None
height: self.texture_size[1]
theme_text_color: 'Custom'
text_color: (1, 1, 1, 1)
padding_y: 15
MDTextFieldRound:
hint_text: 'enter username'
icon_right: 'account'
color_active: 1, 1, 1, 1
pos_hint: {"center_x":.5}
size_hint_x: None
width: 220
font_size: 16
# MDSeparator:
# height: "1dp"
MDTextFieldRound:
hint_text: 'enter password'
icon_right: 'eye-off'
color_active: 1, 1, 1, 1
size_hint_x: None
width: 210
font_size: 15
pos_hint: {"center_x": .5}
password: True
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
MDRectangleFlatButton:
text: 'LOGIN'
pos_hint: {'center_x': .5}
size_hint_x: None
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'left'
root.manager.current = 'Screen2'
Widget:
pos_hint_y: None
height: 30
<SecondScreen>
MDScreen:
md_bg_color: (23/255, 31/255, 40/255, 1)
name: 'Screen2'
MDCard:
md_bg_color: (23/255, 31/255, 47/255, 1)
padding: 10
elevation: 10
orientation: 'vertical'
spacing: 25
pos_hint: {'center_x': .5, "center_y": .5}
size_hint: None, None
size: 340, 400
MDTextButton:
text: '< Back'
padding_x: 0
custom_color: (244/255, 246/255, 214/255, 1)
pos_hint: {"center_y": .1}
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'right'
root.manager.current = 'Screen1'
MDLabel:
id: my_label
text: f'Hello {my_label.text}'
# halign: 'center'
pos_hint: {'center_x': .5}
size_hint_y: None
font_style: 'Body1'
theme_text_color: 'Custom'
text_color: (1, 1, 1, 1)
font_size: 20
height: self.texture_size[1]
padding_y: 15
Widget:
height: 10
您的代码有几个问题:
- 您正试图在用户有机会将文本输入
MDTextField
之前将文本从MDTextField
复制到MDLabel
。此外,ids
尚未在build()
方法中分配。 - 您正在尝试使用
self.root
访问ids
,即ScreenManager
,但ids
是在LoginScreen
和SecondScreen
。见 documentation.
您可以通过在用户输入名称时复制名称并正确使用 ids
来解决这些问题。在你的kv
中,使用text
属性触发复制:
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
on_text: app.set_user_name(self.text)
然后将set_user_name()
方法添加到App
:
def set_user_name(self, name):
my_label = self.root.get_screen('Screen2').ids.my_label
my_label.text = name
当然,从 build()
中删除这些行:
users_name = self.root.ids.users_name
my_label = self.root.ids.my_label
my_label.text = users_name.text
另一种方法,如果您不想擦除 MDLabel
中已有的文本,则使用 MDRectangleFlatButton
作为触发器。在这种情况下,MDTextField 的 kv
变为:
MDTextField:
id: users_name
hint_text: "What's your name?"
helper_text: "What your friends call you.."
helper_text_mode: "on_focus"
pos_hint: {"center_x": .5}
size_hint_x: None
width: 200
这是你的原始代码。将 set_user_name()
方法的触发器添加到 Button
:
MDRectangleFlatButton:
text: 'LOGIN'
pos_hint: {'center_x': .5}
size_hint_x: None
root_button_anim: True
on_press:
# change direction to to non-movable
root.manager.transition.direction = 'left'
root.manager.current = 'Screen2'
app.set_user_name(users_name.text) # trigger name copy
并且set_user_name()
方法必须调整为:
def set_user_name(self, name):
my_label = self.root.get_screen('Screen2').ids.my_label
my_label.text += name # append name rather than over-write