有没有办法从另一个辅助类访问非root类?

时间:2017-04-20 17:04:32

标签: python-2.7 kivy

实际上,我有两个类似的问题:

  1. 可以访问类FaceNameTxtIn,捕获TextInput的文本,从TrainerBtn类不使用全局变量(例如,通过id,self.parent ......我试过没有成功)?
  2. 如何从TrainerBtn的on_release函数访问TrainerBoxLayout的trained_faces_value.text?根类的过程是:

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

    并且程序运行正常,因此我在self.parent(然后是self.parent.parent)中更改了self.root但是进程失败并返回 '流程已完成,退出代码为1'。

  3. (我已经在网上搜索了很多而没有找到符合我问题的解决方案)

    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
    

    HomeScreen类

    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
    

    感谢您的宝贵支持

1 个答案:

答案 0 :(得分:0)

在Kivy内,有不同的可能性来访问其他类。

  • 自我 ...是小部件本身
  • app ...是应用
  • root ...是当前班级的根
  • app.root ...是应用的根

您也可以使用父级和子级访问类,这通常是一个坏主意,因为每次更改结构时都必须调整路径。

一般来说,这些类很多人都知道,这是通过使用Kivy属性来完成的。

正如您在此示例中所看到的,您必须在要使用的上下文中定义属性。 Root经常是一个好地方。

以下示例演示了如何使用Properties来使用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档案
  • 在HomeScreen的根目录
  • 应用程序中的
  • 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"