Python & Kivy:摄像头和换屏

Python & Kivy: Camera and Changing Screen

我想在 Python 中使用 Kivy 构建一个应用程序,但是我遇到了一些错误,我试图解决很多次但我不能。

我想先打开一个相机屏幕。在屏幕中,我们将看到我们的网络摄像头屏幕,底部有 2 个按钮(播放和捕获)。当我按下 Play 时,网络摄像头将打开,如果我按下 Capture 按钮,我想拍摄快照。我在这里构建了工作代码。

按下捕获按钮并拍摄快照后,我想切换屏幕以进入第二个屏幕,它只会在黑色背景中显示基本的 Hello World 语句。

这是我的代码,我的错在哪里?你能修好吗?

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
import time

class CheckScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass

Builder.load_string("""
ScreenManagement:
    CheckScreen:

<CameraClick@ScreenManager>:
    orientation: 'vertical'
    Camera:
        id: camera
        resolution: (640, 480)
        play: False
    ToggleButton:
        text: 'Play'
        on_press: camera.play = not camera.play
        size_hint_y: None
        height: '48dp'
    Button:
        text: 'Capture'
        size_hint_y: None
        height: '48dp'
        on_press:
            root.capture()
            root.manager.transition.direction = 'left'
            root.manager.current = 'check'

<CheckScreen>:
    name: "check"
    Button:
        text: "Next Screen"
        font_size: 50
""")

class CameraClick(BoxLayout):

    def capture(self):
        camera = self.ids['camera']
        timestr = time.strftime("%Y%m%d_%H%M%S")
        camera.export_to_png("IMG_{}.png".format(timestr))
        print("Captured")
        return CheckScreen

class TestCamera(App):

    def build(self):
        return CameraClick()


TestCamera().run()

当我运行这段代码时,它显示;

AttributeError: 'CameraClick' object has no attribute 'manager'

您的代码存在一些问题。正如 John Anderson 在评论中提到的,您的 py/kv 文件中有一个 class 继承自不同的 classes。您还有 2 个屏幕管理器 - 您应该只需要 1 个。我相信您的 CameraClick class 应该只从 kivy 继承 Screen,而不是 ScreenManagerBoxLayout。您可以在 CameraClick class 本身内部定义布局。

您的错误是由于您试图获取您未在任何地方定义的 CameraClick class 的 'manager' 属性。要引用屏幕管理器(看起来就像您正在尝试做的那样),您必须给屏幕管理器一个 'id' 并以这种方式引用它(就像您对相机所做的那样)。

在使用 ScreenManager 时,您应该使用的另一个良好做法是在将屏幕添加到 ScreenManager 小部件时提供您的屏幕以及 ID 和名称。例如而不是

ScreenManagement:
    CheckScreen:

ScreenManagement:
    CheckScreen:
        name: "check_screen"
        id: check_screen

另一个好的做法是将 kv 代码加载到变量中,然后 return 将其加载到主应用程序的 build 方法中。 等等。我已经稍微更改了您的代码,我认为它现在应该可以满足您的期望。花点时间查看它并与您的进行比较,这样您就可以看到差异,如果这不是您要找的,请告诉我。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
import time

class CheckScreen(Screen):
    pass

class CameraClickScreen(Screen):
    def capture(self):
        camera = self.ids['camera']
        timestr = time.strftime("%Y%m%d_%H%M%S")
        camera.export_to_png("IMG_{}.png".format(timestr))


GUI = Builder.load_string("""

GridLayout:
    cols: 1
    ScreenManager:
        id: screen_manager
        CameraClickScreen:
            name: "camera_click_screen"
            id: camera_click_screen
        CheckScreen:
            name: "check_screen"
            id: check_screen



<CameraClickScreen>:
    orientation: 'vertical'
    GridLayout:
        cols: 1
        Camera:
            id: camera
            resolution: (640, 480)
            play: False
        ToggleButton:
            text: 'Play'
            on_press: camera.play = not camera.play
            size_hint_y: None
            height: '48dp'
        Button:
            text: 'Capture'
            size_hint_y: None
            height: '48dp'
            on_press:
                root.capture()
                # root refers to <CameraClickScreen>
                # app refers to TestCamera, app.root refers to the GridLayout: at the top
                app.root.ids['screen_manager'].transition.direction = 'left'
                app.root.ids['screen_manager'].current = 'check_screen'

<CheckScreen>:
    Button:
        text: "Next Screen"
        font_size: 50
""")

class TestCamera(App):

    def build(self):
        return GUI


TestCamera().run()

他们的代码没有问题。要 运行 Android 上的代码,您必须授予它权限。这是代码;您可以将其添加到您的代码顶部:

from android.permissions import request_permissions, Permission
request_permissions([Permission.CAMERA,Permission.WRITE_EXTERNAL_STORAGE,Permission.READ_EXTERNAL_STORAGE])

NOTE: After importing the Android module, the code may give an “import error” while compiling on a desktop, but it will build and run successfully on Android.

此外,不要忘记更改 buildozer.spec 文件中的代码:

android.permissions = CAMERA, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE