2017-04-20 31 views
0

其實,我有2個類似的問題:有沒有辦法從另一個二級類訪問非根類?

  1. 可以訪問類FaceNameTxtIn,捕捉TextInput的文本,從沒有使用全局變量(例如,通過IDS,self.parent類TrainerBtn .. 。我試過沒有成功)?
  2. 如何從TrainerBtn函數on_release訪問TrainerBoxLayout的trained_faces_value.text?從根類的程序是:

    self.root.ids.TrainerBoxLayout.ids.trained_faces_value.text

    ,程序運行正常,所以我已經改變了在self.parent self.root(然後self.parent.parent)但過程失敗並返回 '處理已結束,退出代碼1'。

(我已經搜查了很多網上沒有找到與我的問題匹配的解決方案)

FaceRec.py

Kivy庫

from kivy.app import App 
from kivy.uix.screenmanager import ScreenManager,Screen 
from kivy.uix.widget import Widget 
from kivy.uix.label import Label 
from kivy.uix.button import Button 
from kivy.uix.textinput import TextInput 
from kivy.uix.settings import SettingsWithSidebar 
from kivy.uix.boxlayout import BoxLayout 
from kivy.uix.actionbar import ActionBar 
from kivy.logger import Logger 
from kivy.core.window import Window 

主屏幕類

class ScreenManagement(ScreenManager): 
    pass 

class HomeScreen(Screen): 
    pass 

class HomeActionBar(ActionBar): 
    pass 

class TitleLabel(Label): 
    pass 

class StatusBoxLayout(BoxLayout): 
    pass 

class ErrorsBoxLayout(BoxLayout): 
    pass 

class TrainerBoxLayout(BoxLayout): 
    pass 

class TrainerBtn(Button): 
    def on_release(self): 
     global face_name 
     face_name = face_name.replace(' ','') 
     ... 

class FaceNameTxtIn(TextInput): 
    def on_text(self,instance,value): 
     global face_name 
     face_name = value 

class RecognizerBtn(Button): 
    def on_release(self): 
     ... 

主要類

class FaceRecApp(App): 
    ... 

    def build(self): 
     self.root = HomeScreen() 
     Logger.info('FaceRec.py: FaceRec.kv loaded') 

     self.settings_cls = MySettingsWithSidebar 
     Logger.info('FaceRec.py: MySettingsWithSidebar loaded') 

     ... 

     return self.root 

    ... 

側邊欄的設置

class MySettingsWithSidebar(SettingsWithSidebar): 
    ... 

執行

if __name__ == '__main__': 
    FaceRecApp().run() 

FaceRec.kv

#: import WipeTransition kivy.uix.screenmanager.WipeTransition 

<ScreenManagement>: 
    transition: WipeTransition() 
    HomeScreen: 

<HomeActionBar>: 
    id: HomeActionBar 
    background_color: 0.9,0.9,0.9,0.5 
    pos_hint: {'top':1} 
    size_hint_x: 1 
    ActionView: 
     use_separator: True 
     ActionPrevious: 
      title: 'Home' 
      with_previous: False 
     ActionOverflow: 
     ActionButton: 
      text: 'Logs' 
      on_release: 

     ActionButton: 
      text: 'Settings' 
      icon: 'settings.png' 
      background_down: 'settings.png' 
      on_release: 
       app.open_settings() 

<TitleLabel>: 
    id: TitleLabel 
    text: '[b]FaceRec[/b] - [i]The Face Recognition Project[/i]' 
    color: 0.0,0.3,1,1 
    markup: True 
    font_size: 45 

<StatusBoxLayout>: 
    orientation: 'horizontal' 
    Label: 
     id: status 
     text: 'Status: ' 
    Label: 
     id: status_value 
     text: 'Error' 
     color: 1,0,0,1 

<ErrorsBoxLayout>: 
    id: ErrorsBoxLayout 
    orientation: 'horizontal' 
    Label: 
     id: errors 
     text: 'Errors No: ' 
    Label: 
     id: errors_value 
     text: '...' 

<TrainerBoxLayout>: 
    id: TrainerBoxLayout 
    orientation: 'horizontal' 
    Label: 
     id: trained_faces 
     text: 'Trained faces: ' 
    Label: 
     id: trained_faces_value 
     text: '...' 

<TrainerBtn>: 
    id: TrainerBtn 
    text: 'Press to run the Face Trainer' 
    font_size: 25 
    size_hint: 0.5,1.4 

<FaceNameTxtIn>: 
    id: FaceNameTxtIn 
    hint_text: 'Insert your name and then press the button below' 
    font_size: 19 
    size_hint: 0.5,1.4 
    multiline: False 

<RecognizerBtn>: 
    id: RecognizerBtn 
    text: 'Press to run the Face Recognizer' 
    font_size: 25 
    size_hint: 0.5,1.4 

<HomeScreen>: 
    id: HomeScreen 
    name: 'HomeScreen' 
    canvas.before: 
     Rectangle: 
      pos: self.pos 
      size: self.size 
      source: 'face_pointed.png' 

    HomeActionBar: 
     id: HomeActionBar 

     BoxLayout: 
     orientation: 'vertical' 
     spacing: 70 
     TitleLabel: 
      id: TitleLabel 

     BoxLayout: 
      orientation: 'vertical' 
      spacing: 20 

      StatusBoxLayout: 
       id: StatusBoxLayout 
      ErrorsBoxLayout: 
       id: ErrorsBoxLayout 
      TrainerBoxLayout: 
       id: TrainerBoxLayout 

      FaceNameTxtIn: 
       id: FaceNameTxtIn 

      BoxLayout: 
       orientation: 'horizontal' 

       TrainerBtn: 
        id: TrainerBtn 
       RecognizerBtn: 
        id: RecognizerBtn 

      Label: 
       text: 'Press q to quit the video' 
       font_size: 20 

感謝您的寶貴支持

+0

你可能有更好的運氣越來越要是你把你的例子到你的問題快速回答。看看這個https://stackoverflow.com/help/mcve – EL3PHANTEN

回答

0

在Kivy中有不同的可能性來訪問其他類。

  • 自我 ...是小部件本身
  • 應用 ...是應用
  • ...是當前類
  • 應用程序的根。根 ...是應用程序的根

您也可以使用父母和孩子去上課,這大多是一個糟糕的主意,因爲每當你改變結構時你必須修改路徑。

一般而言,這些類彼此之間相互熟知,這是通過使用Kivy屬性完成的。

正如您在本例中看到的那樣,重要的是您要在要使用的上下文中定義屬性。 Root通常是一個好地方。

以下示例演示如何使用屬性通過kv文件和python操縱數據。

from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.boxlayout import BoxLayout 
from kivy.uix.label import Label 

Builder.load_string(''' 
<MyLabel1>: 
    text:"label 1" 

<MyLabel2> 
    text:"label 2" 

<AppRoot>: 
    lbl_1:lbl_1 
    lbl_2:lbl_2 
    btn_1:btn_1 
    MyLabel1: 
     id: lbl_1 
    BoxLayout: 
     orientation:"vertical" 
     BoxLayout: 
      BoxLayout: 
       Label: 
        text:"ignore this" 
       MyLabel2: 
        id:lbl_2 
    Button: 
     id:btn_1 
     on_press: 
      root.lbl_2.text = root.lbl_1.text 
      root.do_something_in_root() 
      app.do_something_in_app() 
''') 

class MyLabel1(Label): 
    pass 

class MyLabel2(Label): 
    pass 

class AppRoot(BoxLayout): 
    def do_something_in_root(self): 
     print("AppRoot {}".format(self.lbl_1.text)) 
     self.lbl_2.text="set in AppRoot" 

class TestApp(App): 
    def build(self): 
     return AppRoot() 
    def do_something_in_app(self): 
     print("App {}".format(self.root.lbl_2.text)) 
     self.root.lbl_1.text="set in APP" 

if __name__ == '__main__': 
    TestApp().run() 

你的情況,你可以使用下面的方法(在下面的代碼全部實現):

  • 直接從其中的根KV文件
  • 是主屏幕
  • 在應用

    FaceNameTxtIn:FaceNameTxtIn 
    TrainerBtn:TrainerBtn 
    id: HomeScreen 
    name: 'HomeScreen' 
    canvas.before: 
        Rectangle: 
         pos: self.pos 
         size: self.size 
         source: 'face_pointed.png' 
    
    HomeActionBar: 
        id: HomeActionBar 
    
        BoxLayout: 
        orientation: 'vertical' 
        spacing: 70 
        TitleLabel: 
         id: TitleLabel 
    
        BoxLayout: 
         orientation: 'vertical' 
         spacing: 20 
    
         StatusBoxLayout: 
          id: StatusBoxLayout 
         ErrorsBoxLayout: 
          id: ErrorsBoxLayout 
         TrainerBoxLayout: 
          id: TrainerBoxLayout 
    
         FaceNameTxtIn: 
          id: FaceNameTxtIn 
          text:root.TrainerBtn.txt 
    
         BoxLayout: 
          orientation: 'horizontal' 
    
          TrainerBtn: 
           id: TrainerBtn 
           on_press: 
            root.FaceNameTxtIn.text="on press from TrainerBtn" 
            root.on_press_from_btn() 
            app.on_press_from_bnt2() 
    
          RecognizerBtn: 
           id: RecognizerBtn 
    
         Label: 
          text: 'Press q to quit the video' 
          font_size: 20 
    

    在PY文件:

    class HomeScreen(Screen): 
        def __init__(self, **kwargs): 
         super(HomeScreen, self).__init__(**kwargs) 
    
        def on_press_from_btn(self): 
         print("some button was pressed") 
         # the property is defined in the kv 
         self.FaceNameTxtIn.text="value changed from method in app" 
    
    class FaceRecApp(App): 
        def on_press_from_bnt2(self): 
         print("on press executed in app"); 
         app = App.get_running_app() 
         app.root.FaceNameTxtIn.text="value changed from method in app" 
    
+0

And ...我怎樣才能在Python中使用app.root?從TrainerBtn(FaceRec.kv)我可以寫on_release:app.root.ids.TrainerBoxLayout.ids.trained_faces_value.text ='1',但我該怎麼做才能在Python中編寫相同的東西? –

+0

使用這將是可能的,但非常麻煩,因爲你將不得不重寫它,每次你改變佈局結構。最好的方法是使用上面答案中所述的Objectproperties。 – Fari

+0

@ A.B。你可以使用'App.get_running_app()。root.ids' – EL3PHANTEN

相關問題