当我期待一个 TextInput 实例时,Kivy ObjectProperty 是 None,我错过了什么?
Kivy ObjectProperty is None when I'm expecting a TextInput instance, what am I missing?
我正在尝试使用 DropDown
构建一个下拉列表,该小部件的行为应该与 windows 文件资源管理器中看到的类似。
我有一个 TextInput
和一个 Button
,我将 DropDown
与之相关联。当我 运行 以下代码时,出现错误:
Exception has occurred: AttributeError
'NoneType' object has no attribute 'text'
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 34, in on_select
setattr(self.user_choice, 'text', data)
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 45, in on_touch_down
self.dropdown.select(self.text)
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 69, in <module>
MyApp().run()
main.py
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
class TextEntryDropDown(BoxLayout):
user_choice = ObjectProperty(None)
drop_button = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.dropdown = DropDownList(self.user_choice)
for item in ['Option 1', 'Option 2', 'Option 3']:
label = DropDownItem(self.dropdown, text=item, size_hint_y=None, height=30)
self.dropdown.add_widget(label)
class DropDownList(DropDown):
def __init__(self, user_choice, **kwargs):
super().__init__(**kwargs)
self.user_choice = user_choice
def on_select(self, data):
setattr(self.user_choice, 'text', data)
class DropDownItem(Label):
def __init__(self, dropdown, **kwargs):
super().__init__(**kwargs)
self.dropdown = dropdown
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
self.dropdown.select(self.text)
return super().on_touch_down(touch)
class DropButton(Button):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
dropdown = self.parent.dropdown
dropdown.open(self)
return super().on_touch_down(touch)
class MainApp(AnchorLayout):
pass
class MyApp(App):
def build(self):
return MainApp()
if __name__ == '__main__':
MyApp().run()
my.kv
<MainApp>:
anchor_x: 'left'
anchor_y: 'top'
TextEntryDropDown:
<TextEntryDropDown>
size_hint_y: None
height: 30
user_choice: user_choice
drop_button: drop_button
TextInput:
id: user_choice
text: 'Select an option..'
size_hint: (None, None)
height: 30
width: root.width - drop_button.width
DropButton:
id: drop_button
size_hint: (None, None)
height: user_choice.height
width: user_choice.width
我试图追查为什么 user_choice
是 None
,我希望它是对 my.kv
中定义的 TextInput
的引用。知道为什么会这样吗?我不能把我的手指放在上面。
谢谢!
问题是TextEntryDropDown
的ObjectProperties
(user_choice
和drop_button
)在__init__()
的方法中还不可用TextEntryDropDown
。解决方法是在创建 DropDownList
时传递对 TextEntryDropDown
的引用,而不是传递尚未定义的 user_choice
。像这样:
class TextEntryDropDown(BoxLayout):
user_choice = ObjectProperty(None)
drop_button = ObjectProperty(None)
def __init__(self, **kwargs):
print('TextEntryDropDown.__init__(), self.user_choice =', self.user_choice)
super().__init__(**kwargs)
self.dropdown = DropDownList(self) # pass reference to this TextEntryDropDown
for item in ['Option 1', 'Option 2', 'Option 3']:
label = DropDownItem(self.dropdown, text=item, size_hint_y=None, height=30)
self.dropdown.add_widget(label)
然后在 DropDownList
:
class DropDownList(DropDown):
def __init__(self, ted, **kwargs):
super().__init__(**kwargs)
self.textEntryDropDown = ted # save reference to the TextEntryDropDown
# self.user_choice = user_choice
def on_select(self, data):
self.textEntryDropDown.user_choice.text = data # use TextEntryDropDown to access now available user_choice ObjectProperty
# setattr(self.user_choice, 'text', data)
问题是您在 .kv 文件的第 20 行创建了一个无限循环。在第 26 行中,您将 drop_button
宽度定义为 user_choice.width
,然后在第 20 行中,您将 user_choice
宽度定义为 root.width - drop_button.width
.
要修复错误,请更改以下内容:
width: root.width - drop_button.width
至
width: drop_button.width
我正在尝试使用 DropDown
构建一个下拉列表,该小部件的行为应该与 windows 文件资源管理器中看到的类似。
我有一个 TextInput
和一个 Button
,我将 DropDown
与之相关联。当我 运行 以下代码时,出现错误:
Exception has occurred: AttributeError
'NoneType' object has no attribute 'text'
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 34, in on_select
setattr(self.user_choice, 'text', data)
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 45, in on_touch_down
self.dropdown.select(self.text)
File "C:\Users\hanne\Documents\_Educational\_Learning\Python\Kivy\DropDown\B.ii\main.py", line 69, in <module>
MyApp().run()
main.py
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.properties import ObjectProperty
class TextEntryDropDown(BoxLayout):
user_choice = ObjectProperty(None)
drop_button = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.dropdown = DropDownList(self.user_choice)
for item in ['Option 1', 'Option 2', 'Option 3']:
label = DropDownItem(self.dropdown, text=item, size_hint_y=None, height=30)
self.dropdown.add_widget(label)
class DropDownList(DropDown):
def __init__(self, user_choice, **kwargs):
super().__init__(**kwargs)
self.user_choice = user_choice
def on_select(self, data):
setattr(self.user_choice, 'text', data)
class DropDownItem(Label):
def __init__(self, dropdown, **kwargs):
super().__init__(**kwargs)
self.dropdown = dropdown
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
self.dropdown.select(self.text)
return super().on_touch_down(touch)
class DropButton(Button):
def on_touch_down(self, touch):
if self.collide_point(*touch.pos):
dropdown = self.parent.dropdown
dropdown.open(self)
return super().on_touch_down(touch)
class MainApp(AnchorLayout):
pass
class MyApp(App):
def build(self):
return MainApp()
if __name__ == '__main__':
MyApp().run()
my.kv
<MainApp>:
anchor_x: 'left'
anchor_y: 'top'
TextEntryDropDown:
<TextEntryDropDown>
size_hint_y: None
height: 30
user_choice: user_choice
drop_button: drop_button
TextInput:
id: user_choice
text: 'Select an option..'
size_hint: (None, None)
height: 30
width: root.width - drop_button.width
DropButton:
id: drop_button
size_hint: (None, None)
height: user_choice.height
width: user_choice.width
我试图追查为什么 user_choice
是 None
,我希望它是对 my.kv
中定义的 TextInput
的引用。知道为什么会这样吗?我不能把我的手指放在上面。
谢谢!
问题是TextEntryDropDown
的ObjectProperties
(user_choice
和drop_button
)在__init__()
的方法中还不可用TextEntryDropDown
。解决方法是在创建 DropDownList
时传递对 TextEntryDropDown
的引用,而不是传递尚未定义的 user_choice
。像这样:
class TextEntryDropDown(BoxLayout):
user_choice = ObjectProperty(None)
drop_button = ObjectProperty(None)
def __init__(self, **kwargs):
print('TextEntryDropDown.__init__(), self.user_choice =', self.user_choice)
super().__init__(**kwargs)
self.dropdown = DropDownList(self) # pass reference to this TextEntryDropDown
for item in ['Option 1', 'Option 2', 'Option 3']:
label = DropDownItem(self.dropdown, text=item, size_hint_y=None, height=30)
self.dropdown.add_widget(label)
然后在 DropDownList
:
class DropDownList(DropDown):
def __init__(self, ted, **kwargs):
super().__init__(**kwargs)
self.textEntryDropDown = ted # save reference to the TextEntryDropDown
# self.user_choice = user_choice
def on_select(self, data):
self.textEntryDropDown.user_choice.text = data # use TextEntryDropDown to access now available user_choice ObjectProperty
# setattr(self.user_choice, 'text', data)
问题是您在 .kv 文件的第 20 行创建了一个无限循环。在第 26 行中,您将 drop_button
宽度定义为 user_choice.width
,然后在第 20 行中,您将 user_choice
宽度定义为 root.width - drop_button.width
.
要修复错误,请更改以下内容:
width: root.width - drop_button.width
至
width: drop_button.width