-1

我想在 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 未响应”。闲置什么也没说。我完全处于迷雾之中:/

4

1 回答 1

0

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

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()
于 2014-08-12T10:13:39.737 回答