我有一个Tkinter GUI,它显示Matplotlib绘图(Python 2.7.3和Matplotlib 1.2.0rc2),并允许用户配置绘图的某些方面。绘图趋向于变大,因此图形被包装在滚动画布中。配置绘图的一个方面是更改其大小。
现在,虽然绘图一方面可以正常滚动,另一方面也可以调整大小,但这两个操作不能结合使用。下面是演示效果的脚本。(对不起,长度太长了,我不能再短了。)你可以在绘图中滚动(使用滚动条),也可以使绘图变得越来越小(使用按钮)。但是,无论何时滚动,图形都会重置为其原始大小。显然,我希望图形的大小不会因使用滚动条而改变。
import math
from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
import Tkconstants
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def addScrollingFigure(figure, frame):
# set up a canvas with scrollbars
canvas = Canvas(frame)
canvas.grid(row=0, column=0, sticky=Tkconstants.NSEW)
xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
yScrollbar = Scrollbar(frame)
xScrollbar.grid(row=1, column=0, sticky=Tkconstants.EW)
yScrollbar.grid(row=0, column=1, sticky=Tkconstants.NS)
canvas.config(xscrollcommand=xScrollbar.set)
xScrollbar.config(command=canvas.xview)
canvas.config(yscrollcommand=yScrollbar.set)
yScrollbar.config(command=canvas.yview)
# plug in the figure
figAgg = FigureCanvasTkAgg(figure, canvas)
mplCanvas = figAgg.get_tk_widget()
mplCanvas.grid(sticky=Tkconstants.NSEW)
# and connect figure with scrolling region
canvas.create_window(0, 0, window=mplCanvas)
canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL))
def changeSize(figure, factor):
oldSize = figure.get_size_inches()
print "old size is", oldSize
figure.set_size_inches([factor * s for s in oldSize])
print "new size is", figure.get_size_inches()
print
figure.canvas.draw()
if __name__ == "__main__":
root = Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame = Frame(root)
frame.grid(column=0, row=0, sticky=Tkconstants.NSEW)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
figure = plt.figure(dpi=150, figsize=(4, 4))
plt.plot(xrange(10), [math.sin(x) for x in xrange(10)])
addScrollingFigure(figure, frame)
buttonFrame = Frame(root)
buttonFrame.grid(row=0, column=1, sticky=Tkconstants.NS)
biggerButton = Button(buttonFrame, text="larger",
command=lambda : changeSize(figure, 1.5))
biggerButton.grid(column=0, row=0)
smallerButton = Button(buttonFrame, text="smaller",
command=lambda : changeSize(figure, .5))
smallerButton.grid(column=0, row=1)
root.mainloop()
我想我遗漏了一些关于情节是如何发展的
那么,有没有人对调整大小操作后如何让这些滚动条正常运行有任何想法?
我刚刚遇到了同样的问题——据我所知(通过实验),除了figure.set_size_inches()
,您还必须为它设置新的mplCanvas
和画布创建的窗口的大小,在执行figure.canvas.draw()
(然后还强制使用全局vars-或类定义)之前。此外,显然不需要网格mplCanvas
,因为它已经是画布的孩子,这已经是网格。可能想锚定西北,所以在每次调整大小时,情节会在左上角的0.0处重新绘制。
以下是对我有效的方法(我也尝试过使用“内部”框架,如Python Tkinter scrollbar for frame中的方法,但不起作用;有些方法留在代码段的末尾):
import math
import sys
if sys.version_info[0] < 3:
from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
import Tkconstants
else:
from tkinter import Tk, Button, Frame, Canvas, Scrollbar
import tkinter.constants as Tkconstants
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pprint
frame = None
canvas = None
def printBboxes(label=""):
global canvas, mplCanvas, interior, interior_id, cwid
print(" "+label,
"canvas.bbox:", canvas.bbox(Tkconstants.ALL),
"mplCanvas.bbox:", mplCanvas.bbox(Tkconstants.ALL))
def addScrollingFigure(figure, frame):
global canvas, mplCanvas, interior, interior_id, cwid
# set up a canvas with scrollbars
canvas = Canvas(frame)
canvas.grid(row=1, column=1, sticky=Tkconstants.NSEW)
xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
yScrollbar = Scrollbar(frame)
xScrollbar.grid(row=2, column=1, sticky=Tkconstants.EW)
yScrollbar.grid(row=1, column=2, sticky=Tkconstants.NS)
canvas.config(xscrollcommand=xScrollbar.set)
xScrollbar.config(command=canvas.xview)
canvas.config(yscrollcommand=yScrollbar.set)
yScrollbar.config(command=canvas.yview)
# plug in the figure
figAgg = FigureCanvasTkAgg(figure, canvas)
mplCanvas = figAgg.get_tk_widget()
#mplCanvas.grid(sticky=Tkconstants.NSEW)
# and connect figure with scrolling region
cwid = canvas.create_window(0, 0, window=mplCanvas, anchor=Tkconstants.NW)
printBboxes("Init")
canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL),width=200,height=200)
def changeSize(figure, factor):
global canvas, mplCanvas, interior, interior_id, frame, cwid
oldSize = figure.get_size_inches()
print("old size is", oldSize)
figure.set_size_inches([factor * s for s in oldSize])
wi,hi = [i*figure.dpi for i in figure.get_size_inches()]
print("new size is", figure.get_size_inches())
print("new size pixels: ", wi,hi)
mplCanvas.config(width=wi, height=hi) ; printBboxes("A")
#mplCanvas.grid(sticky=Tkconstants.NSEW)
canvas.itemconfigure(cwid, width=wi, height=hi) ; printBboxes("B")
canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL),width=200,height=200)
figure.canvas.draw() ; printBboxes("C")
print()
if __name__ == "__main__":
root = Tk()
root.rowconfigure(1, weight=1)
root.columnconfigure(1, weight=1)
frame = Frame(root)
frame.grid(column=1, row=1, sticky=Tkconstants.NSEW)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(1, weight=1)
figure = plt.figure(dpi=150, figsize=(4, 4))
plt.plot(range(10), [math.sin(x) for x in range(10)])
addScrollingFigure(figure, frame)
buttonFrame = Frame(root)
buttonFrame.grid(row=1, column=2, sticky=Tkconstants.NS)
biggerButton = Button(buttonFrame, text="larger",
command=lambda : changeSize(figure, 1.5))
biggerButton.grid(column=1, row=1)
smallerButton = Button(buttonFrame, text="smaller",
command=lambda : changeSize(figure, .5))
smallerButton.grid(column=1, row=2)
root.mainloop()
"""
interior = Frame(canvas) #Frame(mplCanvas) #cannot
interior_id = canvas.create_window(0, 0, window=interior)#, anchor=Tkconstants.NW)
canvas.config(scrollregion=canvas.bbox("all"),width=200,height=200)
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
interior_id = canvas.create_window(0, 0, window=interior)#, anchor=Tkconstants.NW)
canvas.config(scrollregion=canvas.bbox("all"),width=200,height=200)
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
"""
一个有趣的注意事项是,mplCanvas
将服从大小,如果它变得更大(如单击更大)-但保持旧的大小,如果它变得更小:
$ python2.7 test.py
(' Init', 'canvas.bbox:', (0, 0, 610, 610), 'mplCanvas.bbox:', (0, 0, 600, 600))
## here click "larger":
('old size is', array([ 4.06666667, 4.06666667]))
('new size is', array([ 6.1, 6.1]))
('new size pixels: ', 915.0, 915.0)
(' A', 'canvas.bbox:', (0, 0, 925, 925), 'mplCanvas.bbox:', (0, 0, 926, 926))
(' B', 'canvas.bbox:', (0, 0, 915, 915), 'mplCanvas.bbox:', (0, 0, 926, 926))
(' C', 'canvas.bbox:', (0, 0, 915, 915), 'mplCanvas.bbox:', (0, 0, 926, 926))
()
## here click "larger":
('old size is', array([ 6.1, 6.1]))
('new size is', array([ 9.15, 9.15]))
('new size pixels: ', 1372.4999999999998, 1372.4999999999998)
(' A', 'canvas.bbox:', (0, 0, 915, 915), 'mplCanvas.bbox:', (0, 0, 926, 926))
(' B', 'canvas.bbox:', (0, 0, 1372, 1372), 'mplCanvas.bbox:', (0, 0, 926, 926))
(' C', 'canvas.bbox:', (0, 0, 1372, 1372), 'mplCanvas.bbox:', (0, 0, 1372, 1372))
()
## here click "smaller":
('old size is', array([ 9.14666667, 9.14666667]))
('new size is', array([ 4.57333333, 4.57333333]))
('new size pixels: ', 686.0, 686.0)
(' A', 'canvas.bbox:', (0, 0, 1372, 1372), 'mplCanvas.bbox:', (0, 0, 1372, 1372))
(' B', 'canvas.bbox:', (0, 0, 686, 686), 'mplCanvas.bbox:', (0, 0, 1372, 1372))
(' C', 'canvas.bbox:', (0, 0, 686, 686), 'mplCanvas.bbox:', (0, 0, 1372, 1372))
()
同样的行为mplCanvas可以在Python3.2中看到,以及...不确定这是否是一种错误,或者我也不理解正确的东西
还请注意,这种方式的缩放不会处理轴/tics等字体的大小调整(字体将尝试保持相同的大小);这就是我最终可以通过上面的代码得到的(截短的tics):
...如果你添加轴标签,情况会变得更糟。
无论如何,希望这有帮助,
干杯!
对;在这个答案中的滚动条讨论之后,我最终经历了这个:
...我想我设法得到了一种缩放代码,它也缩放(某种程度上)标签和填充,所以(大约)整个情节适合内部(注意,第二张图片使用imgur的“中等”缩放):
对于非常小的尺寸,标签再次开始消失-但它仍然适用于各种尺寸。
请注意,对于较新的matplotlib
(
$ python2.7 -c 'import matplotlib; print(matplotlib.__version__)'
0.99.3
$ python3.2 -c 'import matplotlib; print(matplotlib.__version__)'
1.2.0
(我确实试着看看是否可以为较旧的matplotlib复制tight_layout
——不幸的是,它需要tight_layout.py中包含的一组相当复杂的函数,而tight_layout.py反过来又要求图形和轴也有特定的规范,v.0.99中没有)
由于subplot\u adjust
采用了相关参数(从0.0到1.0),因此原则上我们只需设置一次,并希望它们能保持我们所需的比例范围。其余部分(字体和labelpad的缩放)请参见下面的代码:
import math
import sys
if sys.version_info[0] < 3:
from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
import Tkconstants
else:
from tkinter import Tk, Button, Frame, Canvas, Scrollbar
import tkinter.constants as Tkconstants
import matplotlib
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pprint, inspect
frame = None
canvas = None
ax = None
def printBboxes(label=""):
global canvas, mplCanvas, interior, interior_id, cwid, figure
print(" "+label,
"canvas.bbox:", canvas.bbox(Tkconstants.ALL),
"mplCanvas.bbox:", mplCanvas.bbox(Tkconstants.ALL),
"subplotpars:", figure.subplotpars.__dict__ )
def addScrollingFigure(figure, frame):
global canvas, mplCanvas, interior, interior_id, cwid
# set up a canvas with scrollbars
canvas = Canvas(frame)
canvas.grid(row=1, column=1, sticky=Tkconstants.NSEW)
xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
yScrollbar = Scrollbar(frame)
xScrollbar.grid(row=2, column=1, sticky=Tkconstants.EW)
yScrollbar.grid(row=1, column=2, sticky=Tkconstants.NS)
canvas.config(xscrollcommand=xScrollbar.set)
xScrollbar.config(command=canvas.xview)
canvas.config(yscrollcommand=yScrollbar.set)
yScrollbar.config(command=canvas.yview)
# plug in the figure
figAgg = FigureCanvasTkAgg(figure, canvas)
mplCanvas = figAgg.get_tk_widget()
# and connect figure with scrolling region
cwid = canvas.create_window(0, 0, window=mplCanvas, anchor=Tkconstants.NW)
printBboxes("Init")
changeSize(figure, 1)
def changeSize(figure, factor):
global canvas, mplCanvas, interior, interior_id, frame, cwid
oldSize = figure.get_size_inches()
print("old size is", oldSize)
figure.set_size_inches([factor * s for s in oldSize])
wi,hi = [i*figure.dpi for i in figure.get_size_inches()]
print("new size is", figure.get_size_inches())
print("new size pixels: ", wi,hi)
mplCanvas.config(width=wi, height=hi) ; printBboxes("A")
canvas.itemconfigure(cwid, width=wi, height=hi) ; printBboxes("B")
canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL),width=200,height=200)
tz.set_fontsize(tz.get_fontsize()*factor)
for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
ax.get_xticklabels() + ax.get_yticklabels()):
item.set_fontsize(item.get_fontsize()*factor)
ax.xaxis.labelpad = ax.xaxis.labelpad*factor
ax.yaxis.labelpad = ax.yaxis.labelpad*factor
#figure.tight_layout() # matplotlib > 1.1.1
figure.subplots_adjust(left=0.2, bottom=0.15, top=0.86)
figure.canvas.draw() ; printBboxes("C")
print()
if __name__ == "__main__":
global root, figure
root = Tk()
root.rowconfigure(1, weight=1)
root.columnconfigure(1, weight=1)
frame = Frame(root)
frame.grid(column=1, row=1, sticky=Tkconstants.NSEW)
frame.rowconfigure(1, weight=1)
frame.columnconfigure(1, weight=1)
figure = plt.figure(dpi=150, figsize=(4, 4))
ax = figure.add_subplot(111)
ax.plot(range(10), [math.sin(x) for x in range(10)])
#tz = figure.text(0.5,0.975,'The master title',horizontalalignment='center', verticalalignment='top')
tz = figure.suptitle('The master title')
ax.set_title('Tk embedding')
ax.set_xlabel('X axis label')
ax.set_ylabel('Y label')
print(tz.get_fontsize()) # 12.0
print(ax.title.get_fontsize(), ax.xaxis.label.get_fontsize(), ax.yaxis.label.get_fontsize()) # 14.4 12.0 12.0
addScrollingFigure(figure, frame)
buttonFrame = Frame(root)
buttonFrame.grid(row=1, column=2, sticky=Tkconstants.NS)
biggerButton = Button(buttonFrame, text="larger",
command=lambda : changeSize(figure, 1.2))
biggerButton.grid(column=1, row=1)
smallerButton = Button(buttonFrame, text="smaller",
command=lambda : changeSize(figure, 0.833))
smallerButton.grid(column=1, row=2)
qButton = Button(buttonFrame, text="quit",
command=lambda : sys.exit(0))
qButton.grid(column=1, row=3)
root.mainloop()
我有一个matplotlib图,嵌入了一个wxpython框架中,带有一些尺寸标注器。在我加入一个传奇之前,一切都很好,但随后施胶器似乎没有与传奇一起工作。 即使通过在拐角处拖动来调整窗口的大小,主图形也会改变大小,但只会显示图例的边缘。 也就是说,请注意,图例在wxFrame中不可见。 编辑: 对于对我有用的解决方案,我希望它在程序自动绘制图形时看起来很好,这样调整参数可以在程序中硬编码,或者,
问题内容: 嗨,我有大尺寸的缓冲…我必须调整缓冲图像的大小… PLZ你能帮助我吗? 问题答案: 更新:不同的算法
问题内容: 如本问题所述(将图像包装到Jframe中),我需要一个jframe来匹配提供的确切图像(图像本身最初是已转换为图像的PDF) 所提供的解决方案确实为我的图像尺寸构建了一个jframe,但实际上看不到所有图像。我需要能够调整jframe的大小,并使图像动态调整为新的jframe大小。失败的话,我想如果我可以滚动jframe或什至放大或缩小,至少可以到达当前无法看到的图像部分。 我需要这个
正如在这个问题中讨论的(将图像包装到Jframe),我需要一个Jframe来匹配精确提供的图像(图像本身最初是一个PDF,已经转换为图像)
编辑:它现在可以工作了,我用画布扩展了这个类,将它的大小设置为宽度和高度,然后将它添加到JFrame,然后打包。这管用!但我认为造成这种情况的原因不是尺寸大小,而是我呈现它的方式,我从JFrame中获得了bufferStrategy,而不是画布,这不是应该的方式。
问题内容: 您好,我有一个QR码图像,我想调整它的大小,当我尝试使用此代码将其调整为小图像时,我总是得到模糊的图像,并且扫描时QR码不再有效,但是当我使用相同的代码将大小调整为大尺寸图像时,它可以正常工作: 有什么问题,我不清楚,请至少给我一个提示,谢谢。 问题答案: 我使用仿射变换来完成此任务,这是我的代码,希望对您有所帮助