Python 为什么子地块没有占用嵌入Tkinter的Matplotlib中figure允许的所有空间?
我想在Tkinter窗口中显示许多子绘图,并能够向下滚动以查看所有大小良好的绘图。然而,它是所有包装和似乎子地块不采取所有的空间允许在我的数字,只限于窗口的空间。我怎样才能使它的间隔更大,子地块更大 我用Python 为什么子地块没有占用嵌入Tkinter的Matplotlib中figure允许的所有空间?,python,user-interface,matplotlib,tkinter,subplot,Python,User Interface,Matplotlib,Tkinter,Subplot,我想在Tkinter窗口中显示许多子绘图,并能够向下滚动以查看所有大小良好的绘图。然而,它是所有包装和似乎子地块不采取所有的空间允许在我的数字,只限于窗口的空间。我怎样才能使它的间隔更大,子地块更大 我用tight_layout()选项尝试了不同的填充,更改了图形大小和Tkinter的其他参数,如我的小部件中的fill或expand 将tkinter作为tk导入 从tkinter导入滚动条 从matplotlib.backends.backend_tkagg导入图CAVASTKAGG 将matp
tight_layout()
选项尝试了不同的填充,更改了图形大小和Tkinter的其他参数,如我的小部件中的fill
或expand
将tkinter作为tk导入
从tkinter导入滚动条
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
将matplotlib.pyplot作为plt导入
类可滚动窗口:
定义初始化(自、主、图、**选项):
主几何体(“%dx%d+0+0”%(800500))
主焦点集()
fig_wrapper=tk.Frame(主控,宽度=800,高度=fig.get_figheight())
fig_wrapper.pack(fill=tk.BOTH,expand=True)
fig_canvas=FigureCanvasTkAgg(fig,master=fig_包装器)
scrollbar=scrollbar(fig\u包装,orient=tk.VERTICAL,command=fig\u canvas.get\u tk\u widget().yview)
滚动条.pack(side=tk.RIGHT,fill=tk.Y)
fig_canvas.get_tk_widget().pack(fill=tk.BOTH,side=tk.LEFT,expand=True)
fig_canvas.get_tk_widget().config(yscrollcommand=scrollbar.set,scrollregion=fig_canvas.get_tk_widget().bbox(“全部”),宽度=800,高度=1000)
n列,n行=3,11
图,轴=plt.子批次(图大小=(n列,n行*2),ncols=n列,nrows=n行)
对于范围内的i(轴形状[0]):
对于范围内的j(轴形状[1]):
轴[i,j]。集xlabel(“xlabel”)
轴[i,j]。设置_ylabel(“ylabel”)
图1紧_布局图()
showStatsWindow=tk.tk()
showStatsWindow=可滚动窗口(showStatsWindow,图)
showStatsWindow.mainloop()
下面是一个例子,其中有一个空图,显示了它的外观。我想每行有3或4个子批次,但都挤在一起了。正如您所看到的,我的窗口中有更多的空间,它随着figsize参数的变化而变化,但它都是空白的
首先让我从显示matplotlib图的
tkinter窗口的大小开始,例如子图。实际上,它是一个固定的窗口大小master.geometry(“%dx%d+0+0”%(800500))
,这让你很困扰
当您只需使用tkinter窗口时,它将自动调整自身大小,使其符合图形大小。反过来,如果调整大小,图形也会调整大小。对于上述问题,有一个简单的解决方法
- 替换以下行:
master.geometry("%dx%d+0+0" % (800, 500))
- 与:
master.resizable(width=False, height=False)
防止调整tkinter窗口的大小。
现在,要使子批的大小变大或变小,可以通过相应地更改figsize=()
参数来更改它
fig, axes = plt.subplots(ncols=n_col, nrows=n_row, figsize=(7.5, 25))
我必须建议您使用PyQT5
,这在您给定的场景中更可行。下面给出了一个工作的示例,其中不调用tkinter
自定义操作,例如pack()
和config()
等
Qt5
将图形放入带有滚动条的画布中,这样图形将保留其原始大小,并且可以在Qt窗口中滚动。您不必在类中处理细节,只需在脚本末尾处理调用
访问参考:
以下是使用PyQT5
得到的结果:
问题在于,如果您想了解如何正确设置滚动条,则滚动条的设置方式不正确。请退出此项并
您绘制图形的框架没有展开
下面是我如何修复它的
import tkinter as tk
from tkinter import Scrollbar
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
class ScrollableWindow:
def __init__(self, master, fig, **options):
def on_configure(event):
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.configure(scrollregion=canvas.bbox('all'))
# expand canvas_frame when canvas changes its size
canvas_width = event.width
canvas.itemconfig(canvas_frame, width=canvas_width)
# --- create canvas with scrollbar ---
canvas = tk.Canvas(master, )
canvas.pack(side=tk.LEFT, fill='both', expand=True)
scrollbar = tk.Scrollbar(master, command=canvas.yview)
scrollbar.pack(side=tk.RIGHT, fill='both')
canvas.configure(yscrollcommand=scrollbar.set)
# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.bind('<Configure>', on_configure)
# --- put frame in canvas ---
fig_wrapper = tk.Frame(canvas)
canvas_frame= canvas.create_window((0, 0), window=fig_wrapper,)
master.geometry("%dx%d+0+0" % (800, 500))
master.focus_set()
fig_canvas = FigureCanvasTkAgg(fig, master=fig_wrapper)
fig_canvas.get_tk_widget().pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
n_col, n_row = 3, 11
fig, axes = plt.subplots(figsize=(n_col*2,n_row*2), ncols=n_col, nrows=n_row,)
for i in range(axes.shape[0]):
for j in range(axes.shape[1]):
axes[i,j].set_xlabel("xlabel")
axes[i,j].set_ylabel("ylabel")
fig.tight_layout()
showStatsWindow = tk.Tk()
showStatsWindow_ = ScrollableWindow(showStatsWindow, fig)
showStatsWindow.mainloop()
将tkinter作为tk导入
从tkinter导入滚动条
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
将matplotlib.pyplot作为plt导入
类可滚动窗口:
定义初始化(自、主、图、**选项):
def on_配置(事件):
#启动“mainloop”后更新scrollregion
#当所有小部件都在画布中时
configure(scrollregion=canvas.bbox('all'))
#当画布更改其大小时展开画布框架
画布宽度=event.width
itemconfig(canvas\u frame,width=canvas\u width)
#---使用滚动条创建画布---
canvas=tk.canvas(master,)
canvas.pack(side=tk.LEFT,fill='both',expand=True)
scrollbar=tk.scrollbar(主控,命令=canvas.yview)
scrollbar.pack(side=tk.RIGHT,fill='both')
configure(yscrollcommand=scrollbar.set)
#启动“mainloop”后更新scrollregion
#当所有小部件都在画布中时
canvas.bind(“”,在配置上)
#---把框架放在画布上---
fig_wrapper=tk.框架(画布)
canvas\u frame=canvas.create\u window((0,0),window=fig\u wrapper,)
主几何体(“%dx%d+0+0”%(800500))
主焦点集()
fig_canvas=FigureCanvasTkAgg(fig,master=fig_包装器)
fig_canvas.get_tk_widget().pack(fill=tk.BOTH,side=tk.LEFT,expand=True)
n列,n行=3,11
图,轴=plt.子批次(图大小=(n列*2,n行*2),ncols=n列,nrows=n行,)
对于范围内的i(轴形状[0]):
对于范围内的j(轴形状[1]):
轴[i,j]。集xlabel(“xlabel”)
轴[i,j]。设置_ylabel(“ylabel”)
图1紧_布局图()
showStatsWindow=tk.tk()
showStatsWindow=可滚动窗口(showStatsWindow,图)
showStatsWindow.mainloop()
这是我得到的结果
如果需要通过tkinter grid调用此函数,可以进行更多可选自定义
import tkinter as tk
from tkinter import *
from tkinter import Scrollbar
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class ScrollableTkAggY(FigureCanvasTkAgg):
def __init__(self, figure, master, *args, **kwargs):
# --- create canvas with scrollbar ---
self.canvas = tk.Canvas(master)
self.canvas.grid(row=0, column=0, sticky=tk.NSEW)
self.canvas.rowconfigure(0, weight=1)
self.canvas.columnconfigure(0, weight=1)
self.fig_wrapper = tk.Frame(self.canvas)
self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
self.fig_wrapper.rowconfigure(0, weight=1)
self.fig_wrapper.columnconfigure(0, weight=1)
super(ScrollableTkAggY, self).__init__(figure, master=self.fig_wrapper, *args, **kwargs)
self.tkagg = self.get_tk_widget()
self.tkagg.grid(row=0, column=0, sticky=tk.NSEW)
self.vbar = Scrollbar(self.canvas, orient=tk.VERTICAL, command=self.canvas.yview)
self.vbar.grid(row=0, column=1, sticky=tk.NS)
self.canvas.configure(yscrollcommand=self.vbar.set, scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
self.canvas.bind('<Configure>', self.on_configure)
# --- put frame in canvas ---
self.canvas_frame = self.canvas.create_window((0, 0), window=self.fig_wrapper, anchor=tk.NW)
ScrollableTkAggY_meths = vars(ScrollableTkAggY).keys()
methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys()
methods = methods.difference(ScrollableTkAggY_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.canvas, m))
def __str__(self):
return str(self.canvas)
# expand canvas_frame when canvas changes its size
def on_configure(self, event):
# update scrollregion after starting 'mainloop'
self.canvas.configure(scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width - 20)
class ScrollableTkAggX(FigureCanvasTkAgg):
def __init__(self, figure, master, *args, **kwargs):
# --- create canvas with scrollbar ---
self.canvas = tk.Canvas(master)
self.canvas.grid(row=0, column=0, sticky=tk.NSEW)
self.canvas.rowconfigure(0, weight=1)
self.canvas.columnconfigure(0, weight=1)
self.fig_wrapper = tk.Frame(self.canvas)
self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
self.fig_wrapper.rowconfigure(0, weight=1)
self.fig_wrapper.columnconfigure(0, weight=1)
super(ScrollableTkAggX, self).__init__(figure, master=self.fig_wrapper, *args, **kwargs)
self.tkagg = self.get_tk_widget()
self.tkagg.grid(row=0, column=0, sticky=tk.NSEW)
self.hbar = Scrollbar(self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.hbar.grid(row=1, column=0, sticky=tk.EW)
self.canvas.configure(xscrollcommand=self.hbar.set, scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
self.canvas.bind('<Configure>', self.on_configure)
# --- put frame in canvas ---
self.canvas_frame = self.canvas.create_window((0, 0), window=self.fig_wrapper, anchor=tk.NW)
ScrollableTkAggX_meths = vars(ScrollableTkAggX).keys()
methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys()
methods = methods.difference(ScrollableTkAggX_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.canvas, m))
def __str__(self):
return str(self.canvas)
# expand canvas_frame when canvas changes its size
def on_configure(self, event):
# update scrollregion after starting 'mainloop'
self.canvas.configure(scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
canvas_height = event.height
self.canvas.itemconfig(self.canvas_frame, height=canvas_height - 20)
class mclass:
def __init__(self, window):
self.figY = Figure(figsize=(10, 30))
self.axesY = self.figY.subplots(ncols=3, nrows=10)
self.figX = Figure(figsize=(30, 10))
self.axesX = self.figX.subplots(ncols=10, nrows=3)
self.canvasY = ScrollableTkAggY(figure=self.figY, master=window)
self.canvasY.grid(row=0, column=0, sticky='nsew')
self.canvasY.rowconfigure(0, weight=1)
self.canvasY.columnconfigure(0, weight=1)
self.canvasX = ScrollableTkAggX(figure=self.figX, master=window)
self.canvasX.grid(row=1, column=0, sticky='nsew')
self.canvasX.rowconfigure(0, weight=1)
self.canvasX.columnconfigure(0, weight=1)
window.geometry("%dx%d+0+0" % (800, 600))
window.focus_set()
self.do_plot()
def do_plot(self):
# Color used in mpl online documentation.
mpl_grey_rvb = (51. / 255., 51. / 255., 51. / 255.)
self.figY.suptitle("Matplotlib's math rendering engine ScrollableTkAggY",
color=mpl_grey_rvb, fontsize=14, weight='bold')
self.figX.suptitle("Matplotlib's math rendering engine ScrollableTkAggX",
color=mpl_grey_rvb, fontsize=14, weight='bold')
# Plotting features demonstration formulae
for i in range(self.axesY.shape[0]):
for j in range(self.axesY.shape[1]):
self.axesY[i, j].set_xlabel("xlabel")
self.axesY[i, j].set_ylabel("ylabel")
self.figY.tight_layout()
self.canvasY.draw()
for i in range(self.axesX.shape[0]):
for j in range(self.axesX.shape[1]):
self.axesX[i, j].set_xlabel("xlabel")
self.axesX[i, j].set_ylabel("ylabel")
self.figX.tight_layout()
self.canvasX.draw()
if __name__ == '__main__':
window = Tk()
start = mclass(window)
window.rowconfigure(0, weight=1)
window.rowconfigure(1, weight=1)
window.columnconfigure(0, weight=1)
# window.columnconfigure(1, weight=1)
window.mainloop()
将tkinter作为tk导入
从tkinter进口*
从tkinter导入滚动条
从matplotlib.figure导入图形
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG
类ScrollableTkAggY(图CAVASTKAGG):
定义初始值(自身、图形、主参数、*args、**kwargs):
import tkinter as tk
from tkinter import *
from tkinter import Scrollbar
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class ScrollableTkAggY(FigureCanvasTkAgg):
def __init__(self, figure, master, *args, **kwargs):
# --- create canvas with scrollbar ---
self.canvas = tk.Canvas(master)
self.canvas.grid(row=0, column=0, sticky=tk.NSEW)
self.canvas.rowconfigure(0, weight=1)
self.canvas.columnconfigure(0, weight=1)
self.fig_wrapper = tk.Frame(self.canvas)
self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
self.fig_wrapper.rowconfigure(0, weight=1)
self.fig_wrapper.columnconfigure(0, weight=1)
super(ScrollableTkAggY, self).__init__(figure, master=self.fig_wrapper, *args, **kwargs)
self.tkagg = self.get_tk_widget()
self.tkagg.grid(row=0, column=0, sticky=tk.NSEW)
self.vbar = Scrollbar(self.canvas, orient=tk.VERTICAL, command=self.canvas.yview)
self.vbar.grid(row=0, column=1, sticky=tk.NS)
self.canvas.configure(yscrollcommand=self.vbar.set, scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
self.canvas.bind('<Configure>', self.on_configure)
# --- put frame in canvas ---
self.canvas_frame = self.canvas.create_window((0, 0), window=self.fig_wrapper, anchor=tk.NW)
ScrollableTkAggY_meths = vars(ScrollableTkAggY).keys()
methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys()
methods = methods.difference(ScrollableTkAggY_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.canvas, m))
def __str__(self):
return str(self.canvas)
# expand canvas_frame when canvas changes its size
def on_configure(self, event):
# update scrollregion after starting 'mainloop'
self.canvas.configure(scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
canvas_width = event.width
self.canvas.itemconfig(self.canvas_frame, width=canvas_width - 20)
class ScrollableTkAggX(FigureCanvasTkAgg):
def __init__(self, figure, master, *args, **kwargs):
# --- create canvas with scrollbar ---
self.canvas = tk.Canvas(master)
self.canvas.grid(row=0, column=0, sticky=tk.NSEW)
self.canvas.rowconfigure(0, weight=1)
self.canvas.columnconfigure(0, weight=1)
self.fig_wrapper = tk.Frame(self.canvas)
self.fig_wrapper.grid(row=0, column=0, sticky=tk.NSEW)
self.fig_wrapper.rowconfigure(0, weight=1)
self.fig_wrapper.columnconfigure(0, weight=1)
super(ScrollableTkAggX, self).__init__(figure, master=self.fig_wrapper, *args, **kwargs)
self.tkagg = self.get_tk_widget()
self.tkagg.grid(row=0, column=0, sticky=tk.NSEW)
self.hbar = Scrollbar(self.canvas, orient=tk.HORIZONTAL, command=self.canvas.xview)
self.hbar.grid(row=1, column=0, sticky=tk.EW)
self.canvas.configure(xscrollcommand=self.hbar.set, scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
self.canvas.bind('<Configure>', self.on_configure)
# --- put frame in canvas ---
self.canvas_frame = self.canvas.create_window((0, 0), window=self.fig_wrapper, anchor=tk.NW)
ScrollableTkAggX_meths = vars(ScrollableTkAggX).keys()
methods = vars(Pack).keys() | vars(Grid).keys() | vars(Place).keys()
methods = methods.difference(ScrollableTkAggX_meths)
for m in methods:
if m[0] != '_' and m != 'config' and m != 'configure':
setattr(self, m, getattr(self.canvas, m))
def __str__(self):
return str(self.canvas)
# expand canvas_frame when canvas changes its size
def on_configure(self, event):
# update scrollregion after starting 'mainloop'
self.canvas.configure(scrollregion=self.canvas.bbox(tk.ALL))
# when all widgets are in canvas
canvas_height = event.height
self.canvas.itemconfig(self.canvas_frame, height=canvas_height - 20)
class mclass:
def __init__(self, window):
self.figY = Figure(figsize=(10, 30))
self.axesY = self.figY.subplots(ncols=3, nrows=10)
self.figX = Figure(figsize=(30, 10))
self.axesX = self.figX.subplots(ncols=10, nrows=3)
self.canvasY = ScrollableTkAggY(figure=self.figY, master=window)
self.canvasY.grid(row=0, column=0, sticky='nsew')
self.canvasY.rowconfigure(0, weight=1)
self.canvasY.columnconfigure(0, weight=1)
self.canvasX = ScrollableTkAggX(figure=self.figX, master=window)
self.canvasX.grid(row=1, column=0, sticky='nsew')
self.canvasX.rowconfigure(0, weight=1)
self.canvasX.columnconfigure(0, weight=1)
window.geometry("%dx%d+0+0" % (800, 600))
window.focus_set()
self.do_plot()
def do_plot(self):
# Color used in mpl online documentation.
mpl_grey_rvb = (51. / 255., 51. / 255., 51. / 255.)
self.figY.suptitle("Matplotlib's math rendering engine ScrollableTkAggY",
color=mpl_grey_rvb, fontsize=14, weight='bold')
self.figX.suptitle("Matplotlib's math rendering engine ScrollableTkAggX",
color=mpl_grey_rvb, fontsize=14, weight='bold')
# Plotting features demonstration formulae
for i in range(self.axesY.shape[0]):
for j in range(self.axesY.shape[1]):
self.axesY[i, j].set_xlabel("xlabel")
self.axesY[i, j].set_ylabel("ylabel")
self.figY.tight_layout()
self.canvasY.draw()
for i in range(self.axesX.shape[0]):
for j in range(self.axesX.shape[1]):
self.axesX[i, j].set_xlabel("xlabel")
self.axesX[i, j].set_ylabel("ylabel")
self.figX.tight_layout()
self.canvasX.draw()
if __name__ == '__main__':
window = Tk()
start = mclass(window)
window.rowconfigure(0, weight=1)
window.rowconfigure(1, weight=1)
window.columnconfigure(0, weight=1)
# window.columnconfigure(1, weight=1)
window.mainloop()