In my app, I can't creat 2 differents screens with camera for each one. However, I can creat only one screen with camera
my Python code
from kivymd.app import MDApp
from kivy.uix.camera import Camera
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
class ZTest(MDApp):
def build(self):
manager = ScreenManager()
manager.add_widget(FirstLayout(name='First'))
manager.add_widget(SecondLayout(name='Second'))
manager.add_widget(ThirdLayout(name='Third'))
return manager
class FirstLayout(Screen):
def btn1(self):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'Second'
def btn2(self):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'Third'
class SecondLayout(Screen):
cam = Camera()
def on_enter(self, *largs):
self.manager.get_screen('Second').ids.cam1.clear_widgets()
self.cam.play = True
self.manager.get_screen('Second').ids.cam1.add_widget(self.cam)
def press(self):
self.cam.play = False
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'First'
class ThirdLayout(Screen):
cam = Camera()
def on_enter(self, *largs):
self.manager.get_screen('Third').ids.cam2.clear_widgets()
self.cam.play = True
self.manager.get_screen('Third').ids.cam2.add_widget(self.cam)
def press(self):
self.cam.play = False
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'First'
if __name__ == "__main__":
ZTest().run()
My Kivy code 'Ztest.kv'
<FirstLayout>:
MDBoxLayout:
orientation: 'vertical'
spacing: 10
size_hint_y: 0.5
MDBoxLayout:
size_hint_y: 0.5
MDRaisedButton:
id: B1
text:"Second"
md_bg_color: (0, 0, 1, 1)
font_size: 40
size_hint: (0.8, None)
pos_hint: {'center_x':0.5}
on_press: root.btn1()
MDBoxLayout:
size_hint_y: 0.5
MDRaisedButton:
id: B2
text:"Third"
md_bg_color: (1, 0, 0, 1)
font_size: 40
size_hint: (0.8, None)
pos_hint: {'center_x':0.5}
on_press: root.btn2()
<SecondLayout>:
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: bar2
title: "Second Layout"
md_bg_color: (0, 0, 1, 1)
right_action_items:[["arrow-left", lambda x: root.press()]]
BoxLayout:
id: cam1
BoxLayout:
orientation: 'vertical'
MDFloatingActionButton:
icon: "camera"
md_bg_color: (0, 0, 1, 1)
pos_hint: {'center_x':0.5}
<ThirdLayout>:
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: bar2
title: "Third Layout"
md_bg_color: (1, 0, 0, 1)
right_action_items:[["arrow-left", lambda x: root.press()]]
BoxLayout:
id: cam2
BoxLayout:
orientation: 'vertical'
MDFloatingActionButton:
icon: "camera"
md_bg_color: (1, 0, 0, 1)
pos_hint: {'center_x':0.5}
I obtain this error message
[ERROR ] [OpenCV ] Couldn't get image from Camera
Traceback (most recent call last):
File "C:\Users\Admin\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\camera\camera_opencv.py", line 144, in _update
self._buffer = frame.imageData
AttributeError: 'NoneType' object has no attribute 'imageData'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Admin\AppData\Local\Programs\Python\Python36\lib\site-packages\kivy\core\camera\camera_opencv.py", line 148, in _update
self._buffer = frame.reshape(-1)
AttributeError: 'NoneType' object has no attribute 'reshape'
But when I delete the ThirdLayout class, the code and the camera operate properly. So, I don't understand if the problem is related to the methode of creating another screen, or the problem is related to method of calling the Camera.
This is due to the fact that you create 2 cameras, I would advise you to create 1 instance of the Camera
class and then use it wherever you want, without forgetting to remove the camera from the previous launch location (layout).
from kivymd.app import MDApp
from kivy.uix.camera import Camera
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.lang.builder import Builder
Builder.load_string("""
<FirstLayout>:
MDBoxLayout:
orientation: 'vertical'
spacing: 10
size_hint_y: 0.5
MDBoxLayout:
size_hint_y: 0.5
MDRaisedButton:
id: B1
text:"Second"
md_bg_color: (0, 0, 1, 1)
font_size: 40
size_hint: (0.8, None)
pos_hint: {'center_x':0.5}
on_press: root.btn1()
MDBoxLayout:
size_hint_y: 0.5
MDRaisedButton:
id: B2
text:"Third"
md_bg_color: (1, 0, 0, 1)
font_size: 40
size_hint: (0.8, None)
pos_hint: {'center_x':0.5}
on_press: root.btn2()
<SecondLayout>:
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: bar2
title: "Second Layout"
md_bg_color: (0, 0, 1, 1)
right_action_items:[["arrow-left", lambda x: root.press()]]
BoxLayout:
id: cam1
BoxLayout:
orientation: 'vertical'
MDFloatingActionButton:
icon: "camera"
md_bg_color: (0, 0, 1, 1)
pos_hint: {'center_x':0.5}
<ThirdLayout>:
BoxLayout:
orientation: 'vertical'
MDToolbar:
id: bar2
title: "Third Layout"
md_bg_color: (1, 0, 0, 1)
right_action_items:[["arrow-left", lambda x: root.press()]]
BoxLayout:
id: cam2
BoxLayout:
orientation: 'vertical'
MDFloatingActionButton:
icon: "camera"
md_bg_color: (1, 0, 0, 1)
pos_hint: {'center_x':0.5}
""")
camera = None
class ZTest(MDApp):
def __init__(self, **kwargs):
super().__init__(**kwargs)
global camera
camera = Camera()
def build(self):
manager = ScreenManager()
manager.add_widget(FirstLayout(name='First'))
manager.add_widget(SecondLayout(name='Second'))
manager.add_widget(ThirdLayout(name='Third'))
return manager
class FirstLayout(Screen):
def btn1(self):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'Second'
def btn2(self):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'Third'
class SecondLayout(Screen):
def __init__(self, **kw):
super().__init__(**kw)
global camera
self.cam = camera
def on_enter(self, *largs):
self.manager.get_screen('Second').ids.cam1.clear_widgets()
self.manager.get_screen('Third').ids.cam2.clear_widgets()
self.cam.play = True
self.manager.get_screen('Second').ids.cam1.add_widget(self.cam)
def press(self):
self.cam.play = False
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'First'
class ThirdLayout(Screen):
def __init__(self, **kw):
super().__init__(**kw)
global camera
self.cam = camera
def on_enter(self, *largs):
self.manager.get_screen('Second').ids.cam1.clear_widgets()
self.manager.get_screen('Third').ids.cam2.clear_widgets()
self.cam.play = True
self.manager.get_screen('Third').ids.cam2.add_widget(self.cam)
def press(self):
self.cam.play = False
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'First'
if __name__ == "__main__":
ZTest().run()