pygame.camera“livefeed”在一个tkinter窗口内(在raspbian上)

时间:2017-11-23 13:50:26

标签: python tkinter camera pygame

我已经考虑在tkinter窗口中嵌入一个pygame窗口(参考:Embed Pygame in Tkinter

我想用它来嵌入pygame.camera模块制作的快照(一旦它可能是一个livefeed)

在评论中,当评论os.environ['SDL_VIDEODRIVER'] = 'windib'时,代码应该与Linux(在raspbian上运行)一起使用

但是我不能让嵌入工作也不能用pygame制作快照,我无法弄清楚是什么导致了这个问题。这是我写的代码:

import pygame as pg
import pygame.camera
import tkinter as tk
import os
import threading as th
tk.Frame = tk.LabelFrame

def start():
    root = tk.Tk()
    run = Viewer(root)
    return run

class Viewer(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.screen_width = parent.winfo_screenwidth()
        self.screen_height = parent.winfo_screenheight()
        self.startup(self.screen_width, self.screen_height)
    def startup(self, width, height):
        self.parent.protocol('WM_DELETE_WINDOW', self.parent.destroy)
        Viewer.embed = tk.Frame(self.parent, width=650, height=490)
        Viewer.embed.pack(side = tk.LEFT)
        self.buttonFrame = tk.Frame(self.parent, width=100, height=490)
        self.buttonFrame.pack(side = tk.RIGHT)
        self.refresh = tk.Button(self.buttonFrame,
                                 text='Refresh',
                                 command=self.refresh)
        self.refresh.pack()
    def refresh(self):
        self.c = Capture()
        self.c.snap()


class Capture(Viewer):
    def __init__(self):
        os.environ['SDL_WINDOWID'] = str(Viewer.embed.winfo_id())
        self.size = (640,480)
        self.display = pg.display.set_mode(self.size)
        self.clist = pg.camera.list_cameras()
        if not self.clist:
            raise ValueError("Sorry, no cameras detected.")
        self.cam = pg.camera.Camera(self.clist[0], self.size)
        self.cam.start()
        self.snapshot = pg.surface.Surface(self.size, 0, self.display)

        self.event = th.Thread(target=self.eventCatcher)
        self.event.start()
    def snap(self):
        self.snapshot = self.cam.get_image(self.snapshot)
    def eventCatcher(self):
        closed = False
        while not closed:
            events = pg.event.get()
            for e in events:
                if e.type == pg.QUIT:
                    self.cam.stop()
                    closed = True

pg.init()
pg.camera.init()
main = start()
main.mainloop()

This is what it looks like

1 个答案:

答案 0 :(得分:1)

设置pygame

后,您必须使用os.environ['SDL_WINDOWID']
os.environ['SDL_WINDOWID'] = str(...)
pygame.init()

编辑:适用于Linux Mint 18.2

import pygame as pg
import pygame.camera
import tkinter as tk
import os
import threading as th

#tk.Frame = tk.LabelFrame

class Viewer(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent # there is self.master which keeps parent

        self.parent.protocol('WM_DELETE_WINDOW', self.parent.destroy)

        self.screen_width = parent.winfo_screenwidth()
        self.screen_height = parent.winfo_screenheight()

        self.embed = tk.Frame(self.parent, width=650, height=490)
        self.embed.pack(side='left')

        self.buttonFrame = tk.Frame(self.parent, width=100, height=490)
        self.buttonFrame.pack(side='right')

        self.parent.update() # need it to get embed.winfo_id() in Capture

        self.c = Capture(self)

        self.refreshButton = tk.Button(self.buttonFrame,
                                 text='Refresh',
                                 command=self.refresh)
        self.refreshButton.pack()

    def refresh(self):
        self.c.snap()


class Capture():

    def __init__(self, parent):
        os.environ['SDL_WINDOWID'] = str(parent.embed.winfo_id())

        pg.display.init()
        pg.camera.init()

        self.size = (640,480)
        self.display = pg.display.set_mode(self.size)
        self.display.fill(pg.Color(255,255,255))

        pg.display.update()

        self.clist = pg.camera.list_cameras()

        if not self.clist:
            raise ValueError("Sorry, no cameras detected.")
        print('cameras:', self.clist)

        self.cam = pg.camera.Camera(self.clist[0], self.size)
        self.cam.start()

        self.snapshot = pg.surface.Surface(self.size, 0, self.display)

        self.event = th.Thread(target=self.eventCatcher)
        self.event.start()

    def snap(self):
        print('snap ready:', self.cam.query_image())
        self.cam.get_image(self.snapshot)
        self.display.blit(self.snapshot, self.snapshot.get_rect())
        pg.display.update()

    def eventCatcher(self):
        closed = False
        while not closed:
            events = pg.event.get()
            for e in events:
                if e.type == pg.QUIT:
                    self.cam.stop()
                    closed = True

root = tk.Tk()
run = Viewer(root)
root.mainloop()