0
##### 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 行中进行评论,但仍然遇到相同的错误。

如果我在锻炼.kv 第 45 行注释并取消注释第 46 行,则代码可以编译,并且 main.py 中的第 46 行可以打印出“NumNum”,这意味着 sm 确实具有属性名称。

4

1 回答 1

0

看起来是时间问题。kv 文件中的逻辑在构建 SecondScreen 对象期间执行,此时其“manager”属性尚未填充。由于尚未填充,它的值为“None”,并且 NoneType 没有 name 属性。

现在,为什么 manager 属性的值为 None?好吧,根据 Kivy 的文档,这个属性是“在将屏幕添加到管理器时设置的”。您初始化之后正在执行的操作。

因此,当您在 main.py 中打印出值时,已经填充了 manager 属性,但是当您在初始化期间调用的 .kv 文件中执行此操作时,您的属性中有一个 NoneType。

你能做些什么呢?好吧,一种方法是将 .kv 中的违规行更改为:

text: root.manager.name if root.manager else ""

这将应对初始化期间 manager 属性为 None 的情况,并且稍后更新 manager 属性时, text 属性应自动更新。不过,也许有一种更优雅的方法可以做到这一点。

于 2015-11-07T20:52:25.387 回答