2015-10-23 65 views
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行中有一個錯誤。我在第37或40行的main.py中嘗試發表評論,但仍然有同樣的錯誤。Kivy編譯錯誤「NoneType」對象沒有「名稱」屬性

如果我在workout.kv第45行中註釋並取消註釋第46行,則可以編寫代碼,main.py中的第46行可以打印出「NumNum」,這意味着sm確實具有屬性名稱。

回答

0

看起來像是一個計時問題。在構建SecondScreen對象期間執行kv文件中的邏輯,此時其「manager」屬性尚未填充。由於它尚未填充,因此其值爲「無」,而且一個NoneType沒有名稱屬性。

現在,爲什麼經理屬性的值爲None?那麼,根據Kivy的文檔,這個屬性是「當屏幕添加到經理時設置的。」你在做什麼之後初始化。

所以,當你在main.py打印出來的值,該管理器屬性已經被填充,但是當你在.kv文件,該文件在初始化調用做到這一點,你必須在NoneType你的財產。

你能做些什麼呢? 那麼,一個辦法是在.kv改變違規行:

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

這將與管理器屬性是在初始化過程中無應付,並且當經理屬性以後更新,文本屬性應自動更新。不過,也許有一種更優雅的方式來做到這一點。

相關問題