python - 在 Tkinter 首次运行问题上调整画布大小
问题描述
我想制作一个以小窗口开始的程序,然后当给定图像路径时,它会最大化屏幕并将图像放在中心。
如果你运行下面的代码,你会看到窗口最大化,图像被加载到内存中,代码运行没有错误,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
单击按钮后的区别。
我在这个问题上读到了一个类似的问题,他建议绑定"<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()
视频中应该发生的事情:我点击运行,图像立即显示,无需点击修复按钮。
解决方案
改变
self.root.state("zoomed")
到self.root.state("normal")
在您的代码中(我正在使用 Python3)我只能得到:
[
上图,从How to get tkinter canvas to dynamic resize to window width?开始播放了一点点?
现在代码似乎对我有用:
from time import sleep
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)
print(kwargs)
Canvas.__init__(self,parent,**kwargs)
self.bind("<Configure>", self.on_resize)
# self.height = self.winfo_reqheight()
# self.width = self.winfo_reqwidth()
self.height = self.winfo_height()
self.width = self.winfo_width()
# self.height = height
# self.width = width
# self.__dict__.update(kwargs)
def on_resize(self,event):
""" determine the ratio of old width/height to new width/height"""
wscale = (event.width)//self.width
hscale = (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.pippo = Tk()
self.name = name # Filename
self.myframe = Frame(self.pippo)
self.myframe.pack(side = BOTTOM, expand=YES)
# myframe.pack(fill=BOTH, expand='TRUE')
self.cv = ResizingCanvas(self.myframe, width=850, height=400, bg="dark grey", highlightthickness=0)
self.cv.pack(fill=BOTH, expand=YES)
# sleep(2)
self.b = Button(self.myframe, text = 'Fix', command = self.fix)#.grid(row=1,column=1)
self.b.pack(side=TOP)
self.open_img()
# self.pippo.mainloop() ## use it if you eliminate def run
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.pippo.winfo_screenwidth()/2,
# self.pippo.winfo_screenheight()/2, image=self.img, tags=('all'))
self.cv.create_image(self.pippo.winfo_width()/2,
self.pippo.winfo_reqheight()/2, image=self.img, tags=('all'))
def open_img(self, event=''):
self.pimg = Image.open(self.name)
self.pippo.state("normal")
self.draw_image(self.pimg)
def fix(self, event=''):
self.draw_image(self.pimg)
def run(self):
self.pippo.mainloop()
if __name__ == "__main__":
path = 'example.png'
app = main(path)
app.run()
虽然不知道您的问题,但想确保您的起始示例正常工作。让我知道它是否与 python/pillow/tkinter 版本或其他有关
这是我按下修复按钮后在广告之前的窗口图像结果:
最后发现只要你使用你的代码就可以工作
self.root.attributes('-zoomed', True) instead of `self.root.state("zoomed")`
推荐阅读
- kubernetes - 设置配置 Kubernetes 调度程序间隔?
- c - c中的动态内存分配会引发特定大小的错误
- string - 使用 utl_match.jaro_winkler 时如何提高比较质量?
- git - 软重置后返回最新提交
- spring - 如何使用 Cassandra 存储用户实体(“PK 决策唯一 ID 与电子邮件”)
- swift - 如何防止一个 UIView 被另一个 UIView 隐藏?
- php - 表单有时提交数据,有时不提交。Magento 1.9
- mysql - Sails js:从mysql中选择记录?
- jasper-reports - 如何在 Jasper Report 的子报表中水平打印列表
- google-apps-script - 来自 GmailApp 附件的 DriveApp createFile 不起作用