python - Matplotlib 在 GUI 中崩溃

标签 python matplotlib crash tkinter imshow

我想在 gui 中使用 imshow 和 tkinter 绘制一个矩阵。问题是,进一步更新后,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 未响应”。空闲什么也没说。我完全陷入迷雾中:/

最佳答案

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

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()

关于python - Matplotlib 在 GUI 中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25251247/

相关文章:

python - 有没有办法在 React Native 应用程序中使用我的 Python 代码?

python - 在 matplotlib 中使用条件标记

python - 在 Matplotlib 中使用 Hlines 破坏传说

android - MultipartEntity 使我的应用程序崩溃

python - 如何将清理后的文本数据拆分为训练数据集和测试数据集(随机采样除外)

python - 如何(/if)使用 dask 转置分布式 3D numpy 数组?

python - 创建一个新列,将列表中其他两列的内容组合在一起

python - Pandas 条形图 : use aggregated output as x-axis and colors for each group

objective-c - ARC + NSLocalizedString + NSMenuItem#title == 内存问题

javascript - 使用for循环使用整数序列填充数组,而不会导致Chrome崩溃