Matplotlib在gui崩溃

时间:2014-08-11 19:52:06

标签: python matplotlib crash tkinter imshow

我想在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下,没有崩溃。

当光标在图像上方或我缩放/取消图像时,可能会在几秒或几分钟内发生。然后窗口变为白色,弹出窗口显示“pythonw.exe无响应”消息。闲置什么也没说。我完全迷雾了:/

1 个答案:

答案 0 :(得分:0)

我认为问题在于运行while True循环。 尝试使用after方法限制每次重复之间的时间。 以下代码每100ms更新一次画布

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)

def redraw():
    mat = random.randint(0, 2**16-1, (1000, 1000))
    cax.set_data(mat)
    canvas.draw()
    root.after(100, redraw)

redraw()
root.mainloop()