2017-04-20 61 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

相关问题