【问题标题】:Python & Kivy: Camera and Changing ScreenPython & Kivy:相机和换屏
【发布时间】:2019-02-06 10:57:09
【问题描述】:

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

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

按下 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' 对象没有属性 'manager'

【问题讨论】:

  • 不确定这是否是问题所在,但您的CameraClick 类在您的kv 代码中定义为扩展ScreenManager,但在您的py 代码中CameraClick 类定义为扩展BoxLayout。您的py 代码可能优先,因此CameraClick 不会扩展ScreenManager,因此没有manager 属性。

标签: python camera kivy screen


【解决方案1】:

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

您的错误来自您试图获取您尚未在任何地方定义的 CameraClick 类的“经理”属性。要引用屏幕管理器(看起来就是您想要做的),您必须给屏幕管理器一个“id”并以这种方式引用它(就像您的相机一样)。

在使用 ScreenManager 时应该使用的另一个好习惯是在将屏幕添加到 ScreenManager 小部件时提供屏幕和 id 和名称。例如而不是

ScreenManagement:
    CheckScreen:

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

另一个好的做法是将您的kv 代码加载到一个变量中,然后在您的主应用程序的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()

【讨论】:

  • 感谢您的回答,唯一缺少的部分是当我点击播放按钮时,它没有打开相机,而且如果我按下捕获按钮,它正在截取空白屏幕截图。如果我将Label: text: "Camera:" id: camera resolution: (640, 480) play: False 更改为Camera: id: camera resolution: (640, 480) play: False ,它将按我的意愿工作。感谢您的帮助。
  • 哦,对了,当我调试时,我没有使用相机,所以我只是在玩标签。我会更新我的答案以反映您的评论。
【解决方案2】:

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

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

注意:导入 Android 模块后,代码在桌面编译时可能会出现“导入错误”,但会在 Android 上成功构建和运行。

另外,别忘了更改buildozer.spec文件中的代码:

android.permissions = CAMERA, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 2016-08-23
    相关资源
    最近更新 更多