2017-11-23 1 views
1

Ich habe blickte in ein pygame Fenster in einer tkinter Fenster Einbettung (Referenz: Embed Pygame in Tkinter)pygame.camera „Livefeed“ innerhalb eines tkinter Fenster (auf raspbian)

Ich wollte diese verwenden, um einen Schnappschuss einzubetten (einmal das funktioniert möglicherweise ein Livefeed), hergestellt von der pygame.camera Modul

In den Kommentaren es der Code wird gesagt, sollte mit Linux arbeiten (läuft auf raspbian), wenn aus Kommentierung os.environ['SDL_VIDEODRIVER'] = 'windib'

jedoch habe ich nicht die Einbettung bekommen mit pygame arbeiten oder einen Schnappschuss machen, und ich kann nicht herausfinden, was das Problem verursacht. Hier ist der Code, den ich schrieb:

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

+0

innerhalb 'Viewer' haben Sie Methode' refresh (self) 'und Schaltfläche' self.refresh = Button() '- für Python bedeutet dies, dass' Button' die Methode ersetzt. – furas

+0

vielleicht funktioniert ein Code im eingebetteten Frame nicht - fangen Sie an, Codezeilen zu entfernen, bis Sie ein Beispiel bekommen. – furas

Antwort

1

Sie haben pygame zu verwenden, nachdem Sie setzen os.environ['SDL_WINDOWID']

os.environ['SDL_WINDOWID'] = str(...) 
pygame.init() 

EDIT: es funktioniert auf 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() 
+0

Danke! Ich werde das morgen testen. Danke auch für den Hinweis auf den Fehler "self.refresh". – HackXIt

+0

Ich bekomme einen Kernel-Fehler (mit Spyder3 IDE mit seiner integrierten IPython-Konsole), wenn es auf diese Weise ausgeführt wird. Die Kameraerkennung funktioniert, weil ich Ausnahmen erhalte, wenn keine Kameras gefunden werden. ** EDIT: ** Okay Entschuldigung, ich habe einen anderen Teil des Codes vergessen, den Sie in der 'snap()' Methode geändert haben. Jetzt funktioniert es. Sehr große Hilfe :) – HackXIt

+0

Ich sollte Kommentare im Code hinzufügen, wenn ich es änderte - aber ich vergaß;) – furas