【问题标题】:How to make an image and display it on the next page如何制作图像并在下一页显示
【发布时间】:2019-04-08 10:59:55
【问题描述】:

下午好,我使用 Python 和 Kivy 编写了一个简单的相机程序,但我就是无法拍摄。您需要拍摄“ScreenThree”的快照(将其保存在手机内存中)并将生成的图像显示在“ScreenFour”上。

我使用 kivy.uix.camera 来显示相机,使用 kivymd 和 kv 来创建界面。 android.permissions:INTERNET,CAMERA,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.camera import Camera
from kivymd.theming import ThemeManager

import time

Builder.load_string("""
#:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
#:import MDIconButton kivymd.button.MDIconButton
<ScreenOne@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Перейти к созданию фото"
            pos_hint: {'center_x':.50, 'center_y':.50}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenTwo@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Выбрать фон"
            pos_hint: {'center_x':.50, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_one'

<ScreenThree@Screen>:
    id: entry
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Camera:
            id: camera
            index: 0
            resolution: (1280,720)
            play: True  
        MDFillRoundFlatButton:
            text: "take photo"
            pos_hint: {'center_x': 0.50, 'center_y': .10}
            on_press:
                root.capture()   #TAKE PHOTO
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_four'    
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenFour@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
# HERE I NEED TO DISPLAY THE IMAGE
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
""")


class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

class ScreenThree(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

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



class ScreenFour(Screen):
    pass


screen_manager = ScreenManager()


screen_manager.add_widget(ScreenOne(name="screen_one"))
screen_manager.add_widget(ScreenTwo(name="screen_two"))
screen_manager.add_widget(ScreenThree(name="screen_three"))
screen_manager.add_widget(ScreenFour(name="screen_four"))


class Interface(App):

    def build(self):
        return screen_manager

sample_app = Interface()
sample_app.run()

请告诉我,如何修改代码来完成任务。

错误

Take photo White screen

04-08 21:15:19.925   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.933   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.949   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.959   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.966   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.983   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.992   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.999   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0

错误2

04-09 08:27:25.140   796  6243 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-09 08:27:25.146   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420
04-09 08:27:25.146  6164  6198 I python  : Captured
04-09 08:27:25.147  6164  6198 I python  : [ERROR  ] [Image       ] Error reading file IMG_20190409_082724.png
04-09 08:27:25.162   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420
04-09 08:27:25.175   796  6243 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-09 08:27:25.179   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420

【问题讨论】:

    标签: android python-3.x kivy android-camera kivy-language


    【解决方案1】:

    访问照片

    使用以下方法引用照片:

    class ScreenFour(Screen):
    
        def on_pre_enter(self, *args):
            self.ids.img.source = self.manager.ids.entry.photo
    

    解决方案

    注意

    <class-name@widget>: 
    

    这是dynamic class。使用动态类时,无需在 Python 脚本中定义类。

    kv 文件

    • 通过删除所有@Screen,将所有动态类更改为类规则。
    • 添加类规则,&lt;ScreenManagement&gt;:
    • 将所有屏幕实例化为类规则的子级,&lt;ScreenManagement&gt;:
    • 添加id: entry下实例化的孩子,ScreenThree:
    • 实例化,Image: 作为类规则FloatLayout: 的子级,&lt;ScreenFour&gt;:
    • 在实例化子项下添加id: imgImage:

    片段

    #:import MDIconButton kivymd.button.MDIconButton
    
    <ScreenManagement>:
        ScreenOne:
            name: "screen_one"
        ScreenTwo:
            name: "screen_two"
        ScreenThree:
            id: entry
            name: "screen_three"
        ScreenFour:
            name: "screen_four"
    ...
    
    <ScreenFour>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
    
        FloatLayout:
            Image:
                id: img
    

    Py 文件

    • 添加导入语句,from os.path import dirname
    • 添加导入语句,from kivy.properties import StringProperty
    • 添加class ScreenManagement()
    • 删除所有对screen_manager 的引用
    • 声明类属性,photo = StringProperty('')class ScreenThree()
    • 初始化类属性,self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
    • 实现方法on_pre_enter()显示照片。

    片段

    from os.path import dirname
    from kivy.properties import StringProperty
    ...
    class ScreenThree(Screen):
        photo = StringProperty('')
    
        def capture(self):
            camera = self.ids['camera']
            self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
            camera.export_to_png(self.photo)
            print("Captured")
    
    
    class ScreenFour(Screen):
    
        def on_pre_enter(self, *args):
            self.ids.img.source = self.manager.ids.entry.photo
    
    
    class ScreenManagement(ScreenManager):
        pass
    
    
    class Interface(App):
    
        def build(self):
            return ScreenManagement()
    

    示例

    main.py

    from os.path import dirname
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivymd.theming import ThemeManager
    from kivy.properties import StringProperty
    
    import time
    
    Builder.load_string("""
    #:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
    #:import MDIconButton kivymd.button.MDIconButton
    
    <ScreenManagement>:
        ScreenOne:
            name: "screen_one"
        ScreenTwo:
            name: "screen_two"
        ScreenThree:
            name: "screen_three"
            id: entry
        ScreenFour:
            name: "screen_four"
    
    <ScreenOne>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            MDFillRoundFlatButton:
                color: [1,1,1,1]
                text: "Перейти к созданию фото"
                pos_hint: {'center_x':.50, 'center_y':.50}
                on_press:
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_two'
    
    <ScreenTwo>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            MDFillRoundFlatButton:
                color: [1,1,1,1]
                text: "Выбрать фон"
                pos_hint: {'center_x':.50, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_three'
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_one'
    
    <ScreenThree>:
        id: entry
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            Camera:
                id: camera
                index: 0
                resolution: (1280,720)
                play: True  
            MDFillRoundFlatButton:
                text: "take photo"
                pos_hint: {'center_x': 0.50, 'center_y': .10}
                on_press:
                    root.capture()   #TAKE PHOTO
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_four'    
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_two'
    
    <ScreenFour>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            Image:
                id: img
    
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_three'
    """)
    
    
    class ScreenOne(Screen):
        pass
    
    
    class ScreenTwo(Screen):
        theme_cls = ThemeManager()
        theme_cls.primary_palette = 'Blue'
        main_widget = None
    
    
    class ScreenThree(Screen):
        theme_cls = ThemeManager()
        theme_cls.primary_palette = 'Blue'
        main_widget = None
        photo = StringProperty('')
    
        def capture(self):
            camera = self.ids['camera']
            self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
            camera.export_to_png(self.photo)
            print("Captured")
    
    
    class ScreenFour(Screen):
    
        def on_pre_enter(self, *args):
            self.ids.img.source = self.manager.ids.entry.photo
    
    
    class ScreenManagement(ScreenManager):
        pass
    
    
    class Interface(App):
    
        def build(self):
            return ScreenManagement()
    
    
    sample_app = Interface()
    sample_app.run()
    

    输出

    【讨论】:

    • 您好,同样的问题,“拍照”后出现白屏,如何解决?
    • 添加导入语句,from os.path import dirname 并在照片文件名前加上 dirname(__file__),例如self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
    • 错误依旧,点击“拍照”后仍然是白屏,在日志中:“python: [ERROR] [Image] Error reading file /IMG_20190409_192950.png”
    • 您能否在手机上使用图库或照片找到并查看该文件?
    • 没有,我试着找了,在图库中没有显示,也找不到它所在的目录。
    【解决方案2】:
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.uix.camera import Camera
    from kivymd.theming import ThemeManager
    
    import time
    
    filename = ''
    screenfour = ''
    
    Builder.load_string("""
    #:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
    #:import MDIconButton kivymd.button.MDIconButton
    <ScreenOne@Screen>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            MDFillRoundFlatButton:
                color: [1,1,1,1]
                text: "Перейти к созданию фото"
                pos_hint: {'center_x':.50, 'center_y':.50}
                on_press:
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_two'
    
    <ScreenTwo@Screen>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            MDFillRoundFlatButton:
                color: [1,1,1,1]
                text: "Выбрать фон"
                pos_hint: {'center_x':.50, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_three'
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_one'
    
    <ScreenThree@Screen>:
        id: entry
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            Camera:
                id: camera
                index: 0
                resolution: (1280,720)
                play: True
            MDFillRoundFlatButton:
                text: "take photo"
                pos_hint: {'center_x': 0.50, 'center_y': .10}
                on_press:
                    root.capture()   #TAKE PHOTO
                    root.manager.transition.direction = 'up'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_four'
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_two'
    
    <ScreenFour@Screen>:
        canvas:
            Color:
                rgb: [.30,.50,.99]
            Rectangle:
                pos: self.pos
                size: self.size
        FloatLayout:
            Image:
                size: root.width, root.height
                source: ''
                id: imageWid
            MDIconButton:
                icon: 'chevron-double-right'
                pos_hint: {'center_x':.95, 'center_y':.10}
                on_press:
                    root.manager.transition.direction = 'down'
                    root.manager.transition.duration = 1
                    root.manager.current = 'screen_three'
    """)
    
    
    class ScreenOne(Screen):
        pass
    
    
    class ScreenTwo(Screen):
        theme_cls = ThemeManager()
        theme_cls.primary_palette = 'Blue'
        main_widget = None
    
    class ScreenThree(Screen):
        theme_cls = ThemeManager()
        theme_cls.primary_palette = 'Blue'
        main_widget = None
    
        def capture(self):
            camera = self.ids['camera']
            timestr = time.strftime("%Y%m%d_%H%M%S")
            photo = camera.export_to_png("IMG_{}.png".format(timestr))
            global filename, screenfour
            filename = "IMG_{}.png".format(timestr)
            print("Captured")
            screenfour.update()
    
    class ScreenFour(Screen):
        def __init__(self, **kwargs):
            super(ScreenFour, self).__init__(**kwargs)
            global screenfour
            screenfour = self
    
        def update(self, *args):
            global filename
            imageWidget = self.ids['imageWid']
            imageWidget.source = filename
    
    screen_manager = ScreenManager()
    
    screen_manager.add_widget(ScreenOne(name="screen_one"))
    screen_manager.add_widget(ScreenTwo(name="screen_two"))
    screen_manager.add_widget(ScreenThree(name="screen_three"))
    screen_manager.add_widget(ScreenFour(name="screen_four"))
    
    class Interface(App):
    
        def build(self):
            return screen_manager
    
    sample_app = Interface()
    sample_app.run()
    

    您将创建一个global 变量来保存图片的文件名,然后在您的screenfour Screen 中创建一个Image 小部件,您将在其中将图像小部件的源更新为您拍摄的图片的文件名。如有任何问题,请随时与我联系

    【讨论】:

    • 感谢您的回答。我检查了你的代码,我遇到了问题。应用程序启动,当我按下“拍照”按钮时,它转到下一页,它是完全白色的。在应用程序日志中始终出现相同的错误。我补充了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多