我有一个Tkinter GUI,它使用Canvas显示图表。图表的数据来自数据框。显示图表需要大量时间,在此期间Tkinter窗口将被冻结。 我尝试了多线程,但不确定如何在代码中实现。
能否请您告诉我如何避免这种情况?我只附加部分代码。
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
from matplotlib.figure import Figure as Fg
from tkinter import filedialog
from tkinter import tkentrycomplete
import tkinter.messagebox as tm
from ttkthemes import themed_tk as thtk
from tkinter import ttk, Canvas
from matplotlib.backends.backend_tkagg \
import FigureCanvasTkAgg, NavigationToolbar2Tk
import matplotlib.pyplot as plt
from PIL import ImageTk, Image
import pandas as pd
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
self.fig = Fg(figsize=(11.5, 4.6), dpi=100)
self.fig.subplots_adjust(
top=0.85, bottom=0.19, right=0.97, left=0.11)
self.fig.suptitle(
'By ' + self.labels[self.ID].cget('text'),
fontweight='bold', fontsize=11)
plt.rcParams.update({'font.size': 7})
# self.fig.autofmt_xdate(rotation=30)
self.canvas = FigureCanvasTkAgg(self.fig, self)
self.canvas.get_tk_widget().place(x=50, y=240)
self.canvas.get_tk_widget().config(relief=tk.RAISED)
self.toolbar_frame = tk.Frame(master=self, height=20)
self.toolbar_frame.place(x=500, y=700)
self.toolbar = NavigationToolbar2Tk(
self.canvas, self.toolbar_frame)
self.toolbar.config(background='#009da6')
self.toolbar._message_label.config(background='#009da6')
self.toolbar.update()
for button in self.toolbar.winfo_children():
button.config(background='#464646')
self.ax = self.fig.add_subplot(111)
self.ax.grid()
self.ax.format_coord = lambda x, y: ""
self.string = ''
for k, v in dm.items():
self.string = self.string + "{}:{}, ".format(k, v)
self.ax.text(0.2, 0.85, r'Filters: ', ha='center', va='center',
transform=plt.gcf().transFigure,
fontsize=9, color='green')
self.ax.text(0.25, 0.85, self.string[:-2], ha='left', va='center',
transform=plt.gcf().transFigure, fontsize=9)
self.ax.set_ylabel(self.yLabel)
self.df.plot(x=self.labels[self.ID].cget(
'text'), ax=self.ax, kind="bar", fontsize=7, grid=True)
plt.setp(self.ax.get_xticklabels(), rotation=30,
horizontalalignment='right')
self.box = self.ax.get_position()
self.ax.set_position(
[self.box.x0, self.box.y0,
self.box.width * 0.9, self.box.height])
self.ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
self.canvas.draw()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()