我有一个程序,包含各种控件,实时网络摄像头和基于网络摄像头数据的matplotlib图。我希望所有控件都位于左列,而网络摄像头和matplotlib图形位于右列。
尝试使用.grid()方法,画布和框架等不起作用 - python脚本无法执行并无限期挂起。
如何实现这一目标?
最低工作示例:
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()
对于最小工作示例,我试图在左侧获得“情节”和“退出”按钮,并在右侧显示带有matplotlib图的网络摄像头视图。目前,它只是将小部件放在一个溢出屏幕的长列中。
答案 0 :(得分:1)
该行
labelframe = tk.LabelFrame(parent, text="This is a LabelFrame")
可能应该self
而不是parent
。在此之后
labelframe.pack(fill="both", expand="yes", tk.LEFT)
应该有效。由于Controller和labelframe具有相同的父级,并且首先调用了Controller的pack
方法,因此它会在labelframe可能出现的地方设置限制。
在Controller.__init__()
中,在一个不寻常的地方有一个self.pack()
的调用,通常在实例化小部件之后调用它,即
c = Controller(root)
c.pack()
root.mainloop()