简体   繁体   中英

Kivy: Camera does not respect pos_hint (but does respect size_hint)

I'm writing a program in Kivy, and have run into a roadblock. Camera objects (from kivy.uix.camera ) respond to changes in size_hint , but do not respond to changes in pos_hint . For pos_hint, it instead always centers the camera feed in the imaginary box drawn by size_hint (ie if size_hint: (0.5, 0.5) , then the feed would be centered within the bottom left half of the window, regardless of what pos_hint is set to).

Here is a minimum reproducible example. If you want different size_hint or pos_hint values, feel free to alter the values given:

main.py

import kivy
kivy.require('1.11.1')

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.camera import Camera
from kivy.core.window import Window

Window.fullscreen = 'auto'  # uses display's current resolution

class CameraStream(FloatLayout):
    pass


class RootWidget(FloatLayout):
    camera_stream = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(RootWidget, self).__init__(**kwargs)


class LifterApp(App):

    def build(self):
        self.root = RootWidget()
        return self.root


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

lifter.kv

#:kivy 1.11.1

<CameraStream>:
    camera_stream: camera_stream_id

    Camera:
        id: camera_stream_id
        resolution: (320, 240)
        play: True

<RootWidget>:
    camera_stream: camera_stream_id

    CameraStream:
        id: camera_stream_id 
        size_hint: (0.5, 0.5)   # this does work
        #size_hint: (0.1, 0.1)  # ...so does this
        #size_hint: (1, 1)      # ...and this
        pos_hint: {'center_x': 0.1, 'center_y': 0.1}    # NOTE this doesn't work
        #pos_hint: {'center_x': 0.9, 'center_y': 0.9}   # ...neither does this
        #pos_hint: {'x': 0, 'y': 0}                     # ...or this

I figured it out so I'll share my solution. There were two issues with my code. First, I realized that kivy.uix.camera.Camera is derived from kivy.uix.image.Image , so I checked those docs and sure enough, they said:

By default, the image is centered and fits inside the widget bounding box. If you don't want that, you can set allow_stretch to True and keep_ratio to False.

This explains the widget resizing (ie the "imaginary box") but not the actual video feed. The other issue I had was that I was trying to set all the properties under the CameraStream: of <RootWidget> , when I actually needed to set them under the Camera: of <CameraStream> since it is the Camera object I'm modifying, not the CameraStream FloatLayout that contains it.

Resolving both of these issues made it work how I desired. For completeness, here is my updated lifter.kv file (the main.py file was unchanged):

#:kivy 1.11.1

<CameraStream>:
    camera_stream: camera_stream_id

    Camera:
        id: camera_stream_id
        resolution: (320, 240)
        play: True
        allow_stretch: True
        keep_ratio: False
        size_hint: (0.5, 0.5)
        #size_hint: (0.1, 0.1)
        #size_hint: (1, 1)
        pos_hint: {'center_x': 0.1, 'center_y': 0.1}
        #pos_hint: {'center_x': 0.9, 'center_y': 0.9}
        #pos_hint: {'x': 0, 'y': 0}

<RootWidget>:
    camera_stream: camera_stream_id

    CameraStream:
        id: camera_stream_id 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM