Kivy,python:如何从根类(FaceRecApp)访问外部/子类?

Posted

技术标签:

【中文标题】Kivy,python:如何从根类(FaceRecApp)访问外部/子类?【英文标题】:Kivy, python: how to access to an external/child class from the root class (FaceRecApp)? 【发布时间】:2017-09-13 00:36:18 【问题描述】:

如何使用 python 或 kivy 访问另一个类的标签/id 并避免下面的错误? 我在其他帖子中进行了搜索,发现无法通过根类引用另一个类......但是,我不知道有任何其他方法可以做到这一点。我希望你能帮助我。 提前致谢。

FaceRec.py

图书馆

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.settings import SettingsWithSidebar
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.actionbar import ActionBar
from kivy.logger import Logger
from kivy.config import Config

设置屏幕尺寸

Config.set('graphics', 'width', '850')
Config.set('graphics', 'height', '850')

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 FaceRecApp(App):
    def build(self):
        root = HomeScreen()
        Logger.info('FaceRec.py: FaceRec.kv loaded')
        self.settings_cls = MySettingsWithSidebar
        Logger.info('FaceRec.py: MySettingsWithSidebar loaded')

        status = root.ids.StatusBoxLayout.status
        status.font_size = float(self.config.get('General', 'font_size'))
        label = root.ids.label
        label.font_size = float(self.config.get('General', 'font_size'))

        return root

    def build_config(self, config):
        config.setdefaults('General', 'text': 'Default Hello','font_size': 20)

    def build_settings(self, settings):
        settings.add_json_panel('General', self.config, 'Settings.json')

    def on_config_change(self, config, section, key, value):
        Logger.info("FaceRec.py: App.on_config_change: 0, 1, 2, 3".format(config, section, key, value))

        if section == "General":
            if key == "text":
                self.root.ids.label.text = value
            elif key == 'font_size':
                self.root.ids.label.font_size = float(value)
                self.root.ids.StatusBoxLayout.status = float(value)

    def close_settings(self, settings):
        Logger.info("FaceRec.py: App.close_settings: 0".format(settings))
        super(FaceRecApp, self).close_settings(settings)

侧边栏设置

class MySettingsWithSidebar(SettingsWithSidebar):
    def on_close(self):
        Logger.info('FaceRec.py: MySettingsWithSidebar.on_close')

    def on_config_change(self, config, section, key, value):
        Logger.info(
            "FaceRec.py: MySettingsWithSidebar.on_config_change: "
        "0, 1, 2, 3".format(config, section, key, value))

执行

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

FaceRec.kv

ScreenManagement:
HomeScreen:

<HomeActionBar>:
    id: HomeActionBar
    pos_hint: 'bottom':0
    ActionView:
        use_separator: True
        ActionPrevious:
            title: 'Home'
            with_previous: False
        ActionOverflow:
        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: 38

<StatusBoxLayout>:
    orientation: 'horizontal'
    #padding: 100
    Label:
        id: status
        text: 'Status: '
        font_size: 20
    Label:
        id: status_value
        text: 'Error'
        font_size: 20
        color: 1,0,0,1

<ErrorsBoxLayout>:
    id: ErrorsBoxLayout
    orientation: 'horizontal'
    #padding: 100
    Label:
        id: errors
        text: 'Errors No: '
        font_size: 20
    Label:
        id: errors_value
        text: '...'
        font_size: 20

<HomeScreen>:
    id: HomeScreen
    BoxLayout:
        orientation: 'vertical'
        HomeActionBar:
        TitleLabel:

        BoxLayout:
            cols: 2
            orientation: 'vertical'

            StatusBoxLayout:
            ErrorsBoxLayout:

    Label:
        id: label
        text: 'Does it run?'

Settings.json

[
    
        "type": "string",
        "title": "Label caption",
        "desc": "Choose the text that appears in the label",
        "section": "General",
        "key": "text"
    ,
    
        "type": "numeric",
        "title": "Label font size",
        "desc": "Choose the font size the label",
        "section": "General",
        "key": "font_size"
    
]

我尝试访问 label 变量(FaceRecApp、build 和 on_config_change 函数)并且程序运行正常。当我在设置中更改标签的字体大小时,更改已应用到 HomeScreen。然后我添加了以下代码行:

在构建()中:

status = root.ids.StatusBoxLayout.status
status.font_size = float(self.config.get('General', 'font_size'))

在 on_config_change() 中:

self.root.ids.StatusBoxLayout.status = float(value)

结果一直出错:

[INFO              ] [Logger      ] Record log in C:\***\.kivy\logs\kivy_17-04-17_109.txt
[INFO              ] [Kivy        ] v1.9.1
[INFO              ] [Python      ] v2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)]
[INFO              ] [Factory     ] 179 symbols loaded
[INFO              ] [Image       ] Providers: img_tex, img_dds, img_gif, img_sdl2, img_pil (img_ffpyplayer ignored)
[INFO              ] [Text        ] Provider: sdl2
[INFO              ] [OSC         ] using <thread> for socket
[INFO              ] [Window      ] Provider: sdl2
[INFO              ] [GL          ] GLEW initialization succeeded
[INFO              ] [GL          ] OpenGL version <4.5.0 NVIDIA 376.53>
[INFO              ] [GL          ] OpenGL vendor <NVIDIA Corporation>
[INFO              ] [GL          ] OpenGL renderer <GeForce ***/PCIe/SSE2>
[INFO              ] [GL          ] OpenGL parsed version: 4, 5
[INFO              ] [GL          ] Shading version <4.50 NVIDIA>
[INFO              ] [GL          ] Texture max size <16384>
[INFO              ] [GL          ] Texture max units <32>
[INFO              ] [Window      ] auto add sdl2 input provider
[INFO              ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO              ] [FaceRec.py  ] FaceRec.kv loaded
[INFO              ] [FaceRec.py  ] MySettingsWithSidebar loaded
 Traceback (most recent call last):
   File "C:/***/PycharmProjects/face_recognition_2/FaceRec.py", line 114, in <module>
     FaceRecApp().run()
   File "C:\Python27\lib\site-packages\kivy\app.py", line 802, in run
     root = self.build()
   File "C:/***/PycharmProjects/face_recognition_2/FaceRec.py", line 65, in build
     status = root.ids.StatusBoxLayout.status
   File "kivy\properties.pyx", line 757, in     kivy.properties.ObservableDict.__getattr__ (kivy\properties.c:11882)
 AttributeError: 'super' object has no attribute '__getattr__'

Process finished with exit code 1

我已经阅读了这篇文章(以及许多其他文章......): How to access id/widget of different class from a kivy file (.kv)? 但我的程序还没有运行。

再次感谢您的支持。

【问题讨论】:

【参考方案1】:

您忘记在根类 (HomeScreen) 中为 StatusBoxLayout 提供 id。 id 需要在根类中给出,以便能够将其作为 self.root.ids.StatusBoxLayout 访问。 所以在 HomeScreen 中给它它的 id:

<HomeScreen>:
    id: HomeScreen
    BoxLayout:
        orientation: 'vertical'
        HomeActionBar:
        TitleLabel:

        BoxLayout:
            cols: 2
            orientation: 'vertical'

            StatusBoxLayout:
                id: StatusBoxLayout
            ErrorsBoxLayout:
                id: ErrorsBoxLayout

当您使用它时,您不妨也给ErrorsBoxLayout 一个 id,或者您需要通过 id 访问的任何其他类。

现在当您分配 status = root.ids.StatusBoxLayout.status 时,改为这样分配:

status = self.root.ids.StatusBoxLayout.ids.status

您需要在前面加上self,因为稍后在您的App 课程中,您想要获取或设置self.root。但是您没有将root 定义为类属性。 而第二个 ids 是因为 status 是 StatusBoxLayout 的 id 所以你的构建方法应该是这样的:

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

    status = self.root.ids.StatusBoxLayout.ids.status
    status.font_size = float(self.config.get('General', 'font_size'))
    label = self.root.ids.label
    label.font_size = float(self.config.get('General', 'font_size'))

    return self.root

【讨论】:

以上是关于Kivy,python:如何从根类(FaceRecApp)访问外部/子类?的主要内容,如果未能解决你的问题,请参考以下文章

Python+kivy+SQLite:如何一起使用

Python:如何在 Kivy 中创建一个简单的框架?

如何在 python 中获取用户输入(Kivy 框架)

如何在 Python/Kivy 中实现 ScrollView

如何制作kivy文件的单独模块并与python文件集成

如何使用 python 语言在 kivy 中定位图像?