2016-06-29 15 views
1

Ich habe ein Programm mit verschiedenen Steuerelementen, eine Live-Webcam-Feed und eine Matplotlib-Figur basierend auf den Daten der Webcam. Ich möchte, dass sich alle Steuerelemente in einer linken Spalte befinden und die Webcam und die Matplotlib-Abbildung in einer rechten Spalte angezeigt werden.Ich habe Probleme mit Tkinter GUI-Steuerung

Versuche, .grid() -Methoden, Canvases und Frames usw. zu verwenden, funktioniert nicht - das Python-Skript kann nicht ausgeführt werden und bleibt auf unbestimmte Zeit hängen.

Wie kann dies erreicht werden?

Mindestarbeitsbeispiel:

import Tkinter as tk 

import cv2 
from PIL import Image, ImageTk 
import numpy as np 

import matplotlib 
matplotlib.use('TkAgg') 

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
import matplotlib.pyplot as plt 
from matplotlib.figure import Figure 

root = tk.Tk() 
root.bind('<Escape>', lambda e: root.quit()) 
lmain = tk.Label(root) 
lmain.pack() 

class Controller(tk.Frame): 
    def __init__(self, parent=root, camera_index=0): 
     self.camera_index = 0 

     frame = tk.Frame.__init__(self, parent,relief=tk.GROOVE,width=100,height=100,bd=1) 
     self.pack() 
     self.parent = parent 
     self.var = tk.IntVar() 

     self.parent.title('Laser Beam Profiler') 

     labelframe = tk.LabelFrame(parent, text="This is a LabelFrame") 
     labelframe.pack(fill="both", expand="yes") #.grid(row=0, column=0) 

     self.plot = tk.Button(labelframe, text = "Plot", command = self.refresh_plot) 
     self.plot.pack() 
     self.exit = tk.Button(labelframe, text = "Exit", command = self.close_window, compound = tk.BOTTOM) 
     self.exit.pack() 

     self.init_camera() 
     self.show_frame() #initialise camera 
     self.make_fig() 

    def make_fig(self): 
     self.fig = Figure(figsize=(4,4), dpi=100) 
     self.ax = self.fig.add_subplot(111) 

     canvas = FigureCanvasTkAgg(self.fig, self) 
     canvas.show() 
     canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) 

     toolbar = NavigationToolbar2TkAgg(canvas, self) 
     toolbar.update() 
     canvas._tkcanvas.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) 

    def refresh_plot(self): 
     self.ax.plot(self.img[0]) 
     self.fig.canvas.draw() 
     self.ax.clear() 
     print 'updated plot' 

    def init_camera(self): 
     width, height = 400, 300 
     self.cap = cv2.VideoCapture(self.camera_index) 
     if not self.cap: 
      raise Exception("Camera not accessible") 
     self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) 
     self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)    

    def show_frame(self): 
     _, frame = self.cap.read() 
     cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) 

     cv2.putText(cv2image,"Laser Beam profiler", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255)) 
     dim = np.shape(cv2image) 

     img = Image.fromarray(cv2image) 
     imgtk = ImageTk.PhotoImage(image=img) 

     lmain.imgtk = imgtk 
     lmain.configure(image=imgtk) 
     lmain.after(10, self.show_frame) 

     self.img = frame 

    def close_window(self): 
     self.parent.quit() 
     self.parent.destroy() 

Controller().mainloop() 

Für das Mindestarbeitsbeispiel Ich versuche, die ‚Handlung‘ und ‚Ausgang‘ Tasten auf der linken Seite zu bekommen, und die Webcam-Ansicht mit der matplotlib Figur auf dem Recht. Derzeit werden die Widgets nur in einer langen Spalte platziert, die vom Bildschirm überspringt.

+0

ich diesen Code getestet, nachdem sie in meiner Antwort der Änderungen erklärten instanziiert wurde und ich konnte den Videoeingang von meiner Webcam sehen, dh nicht hängen. Wenn dieses Python-Skript einfach hängen bleibt, ist es besser zu überprüfen, ob die Videoquelle funktioniert. –

Antwort

1

Die Linie

labelframe = tk.LabelFrame(parent, text="This is a LabelFrame") 

wahrscheinlich self statt parent haben sollte. Danach

labelframe.pack(fill="both", expand="yes", tk.LEFT) 

sollte funktionieren. Da der Controller und der labelframe das gleiche übergeordnete Element hatten und die Methode pack für den Controller zuerst aufgerufen wurde, wurden Einschränkungen für den labelframe gesetzt.

In Controller.__init__() gibt es einen Aufruf zu self.pack() in etwas ungewöhnlichen Ort, es in der Regel genannt wird gelassen, nachdem das Widget dh

c = Controller(root) 
c.pack() 
root.mainloop() 
+1

Während ich zustimme, dass die Anweisung 'pack' verschoben werden sollte, hat das Verschieben keine Wirkung. –

+1

Danke dafür, aber es behebt immer noch nicht das beschriebene Problem. – Sam

+0

@BryanOakley in diesem Fall hatte es einen Effekt, den ich beim Testen des Codes beobachtet habe. Meine Antwort war immer noch falsch, da ich verpasst hatte, was die Eltern für den "labelframe" waren. –

Verwandte Themen