##### main.py #####
from kivy.app import App
from kivy.app import Widget
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import NumericProperty, ObjectProperty, StringProperty, ListProperty, BooleanProperty
class MainScreen(Screen):
def __init__(self,**kwargs):
super(MainScreen,self).__init__(**kwargs) # implements the features of a GridLayout (the base class of MainScreen)
def save(self):
'''Saves the data from the input to a text file.
It is bound to the save button'''
status = self.ids.workout1.ids.status.active
workout = self.ids.workout1.ids.workoutInput.text
day = self.ids.workout1.ids.dayInput.text
time = self.ids.workout1.ids.timeInput.text
with open('workoutData.txt','a') as f:
f.write('%s, %s, %s, %s\n' %(status, workout, day, time))
return None
def totalTime(self):
'''This function doesn't do anything right now! Add code to compute the total exercise time, and document it in this string'''
return None
class WorkoutLayout(BoxLayout):
pass
class SecondScreen(Screen):
pass
class AppScreenManager(ScreenManager):
name = StringProperty('Num Num') ### <----line 37
def __init__(self,**kwargs):
super(AppScreenManager,self).__init__(**kwargs)
self.name = 'Num Num' ### <----line 40
class WorkoutApp(App):
def build(self):
sm = AppScreenManager()
print (sm.name)
# sm.name="123"
sm.add_widget(MainScreen(name='main'))
sm.add_widget(SecondScreen(name='secondary'))
return sm
if __name__=='__main__':
WorkoutApp().run()
# NOTE: running is diff on diff platforms
# python main.py
# kivy main.py
##### part of workout.kv #####
<MainScreen>:
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
Label:
text: 'Workout'
size_hint_x: 2/3.
Label:
text: 'Day'
size_hint_x: 1/6.
Label:
text: 'Time'
size_hint_x: 1/6.
WorkoutLayout:
id: workout1
WorkoutLayout:
id: workout2
WorkoutLayout:
id: workout3
WorkoutLayout:
id: workout4
WorkoutLayout:
id: workout5
WorkoutLayout:
id: workout6
WorkoutLayout:
id: workout7
BoxLayout:
orientation: 'horizontal'
Button:
text: 'Save'
on_press: root.save()
Button:
text: 'Next screen'
on_press: root.manager.current = 'secondary'
<SecondScreen>:
BoxLayout:
orientation: 'vertical'
Label:
size_hint_y: 3/4.
text: root.manager.name ### <----line 45
# text: 'Hello second screen!' ### <----line 46
Button:
size_hint: (1/4.,1/4.)
text: 'Back to main screen'
on_press: root.manager.current = 'main'
<WorkoutLayout>:
size_hint_x: 1
orientation: 'horizontal'
CheckBox:
id: status
size_hint_x: 1/8.
TextInput:
id: workoutInput
size_hint_x: 5/8.
TextInput:
id: dayInput
size_hint_x: 1/8.
TextInput:
id: timeInput
size_hint_x: 1/8.
TextInput:
multiline: False
这些在线修改了一些示例代码。当我编译时,它显示"NoneType" object has no attribute "name"
,我的kv文件中的第45行出错。我尝试在我的main.py中注释37或40行,但仍然遇到了同样的错误。
如果我在workout.kv第45行中注释并取消注释第46行,则可以编译代码,并且main.py中的第46行可以打印出&#34; NumNum&#34;,这意味着sm确实具有属性名称。
答案 0 :(得分:0)
看起来像是时间问题。在构造SecondScreen对象期间执行kv文件中的逻辑,此时它的管理器&#34;物业尚未填充。由于它尚未填充,因此其值为&#34;无,&#34;并且NoneType没有名称属性。
现在,为什么manager属性的值为None?好吧,根据Kivy的文档,这个属性是在屏幕添加到经理时设置的。&#34;在初始化之后你只是做了什么。
因此,当你在main.py中打印出值时,管理员属性已经被填充,但是当你在初始化期间调用的.kv文件中执行它时,你就是&#39 ;你的房产中有一个NoneType。
你能做些什么? 好吧,一种方法是将.kv中的违规行更改为:
text: root.manager.name if root.manager else ""
这将在初始化期间处理manager属性为None,并且稍后更新manager属性时,text属性应自动更新。也许有更优雅的方式来做到这一点。