You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy点击按钮加载ZBarCam相机,解决提前初始化问题

解决Kivy中ZBarCam延迟初始化与扫码结果获取问题

问题描述

开发Kivy二维码扫描应用,需求是点击「Start Scan」按钮后才启动基于ZBarCam的扫码功能。但使用ScreenManager切换屏幕时,相机在应用启动时就已初始化(指示灯亮起);尝试动态向QrReader屏幕添加ZBarCam来延迟初始化,却无法获取扫描到的symbols(二维码文本)。


初始代码(相机提前初始化)

QrApp.py

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


class QrReader(Screen):
    pass

class ScanButton(Screen):
    pass

class QrApp(App):
    pass

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

qrapp.kv

ScreenManager:
    id: screen_manager
    ScanButton:
        id: scan_btn
        name: 'scan_btn'
        manager: 'screen_manager'
    QrReader:
        id: qr_reader
        name: 'qr_reader'
        manager: 'screen_manager'


<ScanButton>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text:'Start Scan'
            font_size:"50sp"
            color: [0, 255, 255, .67]
            on_press: app.root.current = 'qr_reader'

<QrReader>:
    #:import ZBarCam kivy_garden.zbarcam.ZBarCam
    BoxLayout:
        orientation: 'vertical'
        ZBarCam:
            id:qrcodecam
        Label:
            size_hint: None, None
            size: self.texture_size[0], 50
            text: ' '.join([str(symbol.data) for symbol in qrcodecam.symbols])

尝试的动态添加方案(失败)

通过on_enter方法动态添加ZBarCam,实现了相机延迟初始化,但无法获取扫码结果:

QrApp.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen


class QrReader(Screen):
    def on_enter(self):
        from kivy_garden.zbarcam import ZBarCam
        zbarcam = ZBarCam()
        self.add_widget(zbarcam)
        self.add_widget(Label(
            text='PRINT SYMBOLS', #' '.join([str(symbol.data) for symbol in zbarcam.symbols] 无法运行
            size_hint=(None,None),
            size=(Window.width*0.1, Window.height*0.1),
            center=(Window.width*0.3, Window.height*0.5)))

class ScanButton(Screen):
    pass

class QrApp(App):
    pass

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

qrapp.kv

ScreenManager:
    id: screen_manager
    ScanButton:
        id: scan_btn
        name: 'scan_btn'
        manager: 'screen_manager'
    QrReader:
        id: qr_reader
        name: 'qr_reader'
        manager: 'screen_manager'

<ScanButton>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text:'Start Scan'
            font_size:"50sp"
            color: [0, 255, 255, .67]
            on_press:
                app.root.current = 'qr_reader'


<QrReader>:
    BoxLayout:
        orientation: 'vertical'

解决方案

核心思路是延迟ZBarCam初始化到进入扫码屏幕时,同时绑定symbols事件监听扫码结果,离开屏幕时释放资源:

QrApp.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy_garden.zbarcam import ZBarCam


class QrReader(Screen):
    def on_enter(self, *args):
        # 进入屏幕时才初始化ZBarCam
        self.zbarcam = ZBarCam()
        # 绑定symbols变化事件,实时更新扫码结果
        self.zbarcam.bind(symbols=self.update_scan_result)
        self.add_widget(self.zbarcam)
        
        # 创建结果显示标签
        self.result_label = Label(
            text="扫描二维码...",
            size_hint=(None, None),
            size=(self.width * 0.8, 50),
            pos_hint={"center_x": 0.5, "bottom": 0.1}
        )
        self.add_widget(self.result_label)

    def update_scan_result(self, instance, symbols):
        # 更新标签文本为扫码结果
        if symbols:
            self.result_label.text = f"扫描结果: {' '.join([str(s.data) for s in symbols])}"
        else:
            self.result_label.text = "扫描二维码..."

    def on_leave(self, *args):
        # 离开屏幕时移除组件,释放相机资源
        self.remove_widget(self.zbarcam)
        self.remove_widget(self.result_label)
        del self.zbarcam
        del self.result_label


class ScanButton(Screen):
    pass


class QrApp(App):
    pass


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

qrapp.kv

ScreenManager:
    ScanButton:
        name: 'scan_btn'
    QrReader:
        name: 'qr_reader'

<ScanButton>:
    BoxLayout:
        orientation: 'vertical'
        Button:
            text:'Start Scan'
            font_size:"50sp"
            color: [0, 1, 1, 0.67]  # Kivy颜色值范围为0-1,修正原代码的255值
            on_press: app.root.current = 'qr_reader'

<QrReader>:
    BoxLayout:
        orientation: 'vertical'

关键说明

  1. 延迟初始化:仅在on_enter(进入扫码屏幕)时创建ZBarCam,避免应用启动就激活相机。
  2. 结果监听:通过bind(symbols=self.update_scan_result)监听扫码结果变化,实时更新UI。
  3. 资源释放:on_leave方法中移除并删除组件,确保离开扫码屏幕后相机资源被释放。
  4. 颜色值修正:Kivy中颜色通道为0-1的浮点数,原代码的[0,255,255,.67]会被截断,修正为正确格式。

内容的提问来源于stack exchange,提问作者Dovi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 13:45:27