【发布时间】:2021-11-02 20:02:11
【问题描述】:
我想制作一个以小窗口开始的程序,然后当给定图像路径时,它会最大化屏幕并将图像放置在中心。
如果您运行下面的代码,您将看到窗口最大化,图像被加载到内存中,代码运行没有错误,self.open_image 调用self.draw_image(self.pimg) 运行没有错误,但是图像不存在画布。
如果我点击“修复”按钮并调用self.fix,它会调用self.draw_image(self.pimg),它会正常运行并正确绘制图像。
如何使用相同的参数调用相同的函数两次并得到不同的结果。有什么不同。
我感觉正在发生这种情况,因为在 self.__init__ 末尾没有发生的主循环中发生了一些事情,所以当我第二次调用 self.draw_image 时,self.cv.create_image 能够与可调整大小的画布中的某些内容进行交互。
在这个例子中,我很高兴假设程序将始终作为一个小窗口开始并成为一个最大化的窗口,直到它被关闭,永远不会再次调整大小,但是在我的实际程序中,我想让它更加动态,其中窗口可以合理地调整大小,这只是一个最小的可重现示例。正是出于这个原因,我想使用 ResizingCanvas 类(或类似的类),即使我觉得这很可能是我遇到的问题的原因。
我尝试过使用断点并单步执行代码以观察变量的创建,但我无法看到第一次出现的 self.cv 和单击按钮后的 self.cv 之间的区别。
我在this question 上读到了类似的问题,他建议将"<Configure>" 绑定到画布并将坐标从事件传递到画布。不过这已经在ResizingCanvas中实现了
from tkinter import *
from PIL import Image, ImageTk
class ResizingCanvas(Canvas):
# https://stackoverflow.com/a/22837522/992644
def __init__(self,parent,**kwargs):
Canvas.__init__(self,parent,**kwargs)
self.bind("<Configure>", self.on_resize)
self.height = self.winfo_reqheight()
self.width = self.winfo_reqwidth()
def on_resize(self,event):
""" determine the ratio of old width/height to new width/height"""
wscale = float(event.width)/self.width
hscale = float(event.height)/self.height
self.width = event.width
self.height = event.height
# resize the canvas
self.config(width=self.width, height=self.height)
# rescale all the objects tagged with the "all" tag
self.scale("all",0,0,wscale,hscale)
class main():
def __init__(self, name = None):
self.root = Tk()
self.name = name # Filename
myframe = Frame(self.root)
myframe.pack(fill=BOTH, expand=YES)
self.cv = ResizingCanvas(myframe, width=850, height=400, bg="dark grey", highlightthickness=0)
self.cv.pack(fill=BOTH, expand=YES)
self.b = Button(self.cv, text = 'Fix', command = self.fix).grid(row=1,column=1)
self.open_img()
def draw_image(self, img, x = None, y = None):
""" Handles the drawing of the main image"""
self.img = ImageTk.PhotoImage(img)
self.cv.create_image(self.root.winfo_screenwidth()/2,
self.root.winfo_screenheight()/2, image=self.img, tags=('all'))
def open_img(self, event=''):
self.pimg = Image.open(self.name)
self.root.state("zoomed")
self.draw_image(self.pimg)
def fix(self, event=''):
self.draw_image(self.pimg)
def run(self):
self.root.mainloop()
if __name__ == "__main__":
path = 'example.png'
app = main(path)
app.run()
视频中应该发生的事情: 我点击运行,图像立即显示,无需点击修复按钮。
【问题讨论】:
-
hi @hamsolo474 尝试了您的代码,但无法使其运行我正在添加与我一起使用的偶然版本,但不知道如何回答您的问题
-
@pippo1980 感谢您的回复,我已按原样附上了该错误的视频和我的代码。我在 Windows 10 上运行它,在你的链接中它说 Linux 上的
self.root.attributes('-zoomed', True)相当于 Windows 上的self.root.attributes("-fullscreen", True),我正在寻找最大化而不是全屏。我猜你的问题是由于 Linux 上的 Tkinter 和 Windows 上的 Tkinter 之间的细微差别。感谢您发布修复以使我的示例在 Linux 上运行,如果任何 Windows 用户看到这一点并且也无法运行我的代码,请说些什么。 -
尝试将 #self.pippo.state("zoomed") 从 'def open_png:' 移动到 'def fix:' 你会得到 3 个不同的结果调用相同的函数 3 个不同的时间
-
尝试在 'def on_resize:' 之后添加 'print('EVENT : ' ,event)' 看看你是否能分辨出来
标签: python python-3.x tkinter python-imaging-library tkinter-canvas