我想在 gui 中使用 tkinter 绘制一个带有 imshow 的矩阵。问题是进一步更新后,gui崩溃。我无法在网上找到答案。你能帮帮我吗?
编码:
from numpy import *
from Tkinter import *
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
root = Tk()
f1 = Figure()
canvas = FigureCanvasTkAgg(f1, master=root)
canvas.show()
canvas.get_tk_widget().pack(fill="x")
a = f1.add_subplot(111)
a.get_axes().set_frame_on(True)
ini = [[i] * 100 for i in range(100)]
cax = a.matshow(ini)
while True:
mat = random.randint(0, 2**16-1, (1000, 1000))
cax.set_data(mat)
canvas.draw()
root.mainloop()
感谢您对 fhdrsdg 的建议,但是这样做会在执行重绘期间冻结窗口,这很无聊,尤其是当前一个有很多事情要做时。
这是我的代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Tkinter import Button, Label, Text, Checkbutton, Radiobutton, Frame, Tk, Entry, INSERT, StringVar, IntVar, Toplevel, END
from ttk import Notebook, Combobox
from numpy import arange, zeros, array, uint16, empty, divide, random, ravel
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from matplotlib import cm
from matplotlib.image import AxesImage
import time
from threading import Thread
import os
class Image_direct(Thread):
def __init__(self):
Thread.__init__(self)
self.encore = True
def run(self):
"""This loop can be long ~10s"""
while self.encore:
time.sleep(1)
app.cax.set_extent((0, 1023, 1023, 0))
mat = random.randint(0, 2**16-1, (1024, 1024)).astype("uint16")
app.update_camera(mat)
def stop(self):
self.encore = False
class Deu(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.creer_applets()
def creer_applets(self):
self.fen4 = Frame(fen)
self.fen4.pack(side="bottom", fill="both")
self.fen1 = Frame(fen, width=200)
self.fen1.pack(side="left", fill="both", expand=False)
self.note = Notebook(fen, width=1)
self.tab_mat = Frame(self.note)
self.note.add(self.tab_mat, text = "Caméra", compound="top")
self.note.pack(side="left", fill="both", expand=True)
self.fen3 = Frame(fen, width=250)
self.fen3.pack(side="left", fill="both", expand=False)
Button(self.fen4, text="Quit", command=self.aurevoir).pack(fill="x", side="top")
self.interp = StringVar()
self.interp.set("none")
liste_interp = ["none", "nearest", "bilinear", "bicubic", "spline16", "spline36", "hanning", "hamming", "hermite", "kaiser", "quadric", "catrom", "gaussian", "bessel", "mitchell", "sinc", "lanczos"]
self.choix_interp = Combobox(self.tab_mat, textvariable=self.interp, state="readonly", width=10)
self.choix_interp['values'] = liste_interp
self.cmap = StringVar()
self.cmap.set("jet")
palettes = sorted(m for m in cm.datad if not m.endswith("_r"))
self.choix_palette = Combobox(self.tab_mat, textvariable=self.cmap, state="readonly", width=10)
self.choix_palette['values'] = palettes
self.bouton_palette = Button(self.tab_mat, text="Changer la palette", command=self.changer_cmap)
self.f1 = Figure()
self.canvas1 = FigureCanvasTkAgg(self.f1, master=self.tab_mat)
self.canvas1.show()
self.canvas1.get_tk_widget().pack(fill="both", expand=1)
NavigationToolbar2TkAgg(self.canvas1, self.tab_mat)
self.a = self.f1.add_subplot(111)
self.bg = self.canvas1.copy_from_bbox(self.a.bbox)
self.a.get_axes().set_frame_on(True)
ini = random.randint(0, 2**16-1, (1024, 1024))
self.cax = self.a.matshow(ini, cmap=self.cmap.get(), interpolation=self.interp.get(), picker=True, alpha=1.0)
self.a.format_coord = lambda x, y: 'x=%d, y=%d, z=%d' % (x, y, ini[round(y), round(x)])
self.cbar = self.f1.colorbar(self.cax)
self.cbar.set_label("coups")
self.bouton_palette.pack(side="left")
self.choix_interp.pack(side="left")
self.choix_palette.pack(side="left")
Button(self.tab_mat, text=">", command=lambda: self.changer_cbar(1)).pack(side="right")
self.cbar_auto = IntVar()
self.chb3 = Checkbutton(self.tab_mat, text="Auto?", variable=self.cbar_auto, onvalue=1, offvalue=0, indicatoron=0, command=lambda: self.changer_cbar(0))
self.chb3.select()
self.chb3.pack(side="right")
Button(self.tab_mat, text="<", command=lambda: self.changer_cbar(-1)).pack(side="right")
self.bouton_direct_on = Button(self.fen3, width=20, text="Démarrer le direct", command=self.image_direct_on)
self.bouton_direct_on.place(x=0, y=400)
self.bouton_direct_off = Button(self.fen3, width=20, text="Arrêter le direct", command=self.image_direct_off)
self.bouton_direct_off.config(state="disabled")
self.bouton_direct_off.place(x=0, y=430)
def changer_cbar(self, sens):
if sens == -1:
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=0.9*self.cbar.get_clim()[1])
elif sens == 0 and self.cbar_auto.get():
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=self.cax.get_array().max())
elif sens == 1:
self.cbar.set_clim(vmin=self.cax.get_array().min(), vmax=2*self.cbar.get_clim()[1])
self.cax.set_clim(self.cbar.get_clim())
self.canvas1.restore_region(self.bg)
self.a.draw_artist(self.f1)
self.canvas1.blit(self.f1.bbox)
def changer_cmap(self):
self.cax.set_cmap(self.cmap.get())
self.cax.set_interpolation(self.interp.get())
self.canvas1.draw()
def update_camera(self, mat):
xmin = min([int(i) for i in app.a.get_xlim()])
xmax = max([int(i) for i in app.a.get_xlim()])
ymin = min([int(i) for i in app.a.get_ylim()])
ymax = max([int(i) for i in app.a.get_ylim()])
self.a.format_coord = lambda x, y: 'x=%d, y=%d, z=%d' % (x, y, mat[round(y), round(x)])
self.cax.set_data(mat)
self.changer_cbar(0)
def image_direct_on(self):
self.bouton_direct_off.config(state="normal")
self.bouton_direct_on.config(state="disabled")
self.dire = Image_direct()
self.dire.setDaemon(True)
self.dire.start()
def image_direct_off(self):
self.bouton_direct_off.config(state="disabled")
self.bouton_direct_on.config(state="normal")
self.dire.stop()
del self.dire
def aurevoir(self):
try:
self.dire.isAlive()
except:
pass
else:
self.dire.stop()
fen.quit()
fen.destroy()
if __name__ == '__main__':
fen = Tk()
fen.geometry("1300x750")
app = Deu(fen)
fen.mainloop()
奇怪的是:
当光标在图像上时发生崩溃
在linux下,没有crash。
当光标在图像上或当我缩放/缩小图像时,它可能会在几秒钟或几分钟内发生。然后窗口变为白色,并出现一个弹出窗口,显示消息“pythonw.exe 未响应”。闲置什么也没说。我完全处于迷雾之中:/