[英]Issues resizing a canvas image in tkinter
我正在创建一个自定义 tkinter 框架 class 用于更大的项目。 我现在把它装在一个可用的 state 中,但它有问题。 调用时,class 应该创建一个小部件,该小部件在 canvas object 的上方和左侧创建带有图像项的复选按钮。 我遇到的2个问题:
1) 首次执行时,代码几乎按照需要创建整个小部件,除了 canvas 上的图像直到发生调整大小事件才会出现,比如我抓住 window 的一侧并调整它的大小。
2)然后,当发生调整大小事件时,图像并不总是完全正确地调整大小。 很多时候,特别是如果使用 cursor 快速调整大小,canvas 最终会比图像大,或者图像可能会被 Z05B8C74CBD96FBF2DE4C1A3527 的边缘切掉一点。 在我下面链接的错误调整大小图像中,canvas 是图像下方的黑色峰值。 为什么每次图像大小都与 canvas 不匹配?
值得注意的是,当我使用全屏按钮时,图像根本不会调整大小。 然后当我使用窗口按钮时,图像会调整为全屏大小,从而在小 window 内产生一个巨大的图像。 调整大小事件似乎落后了一步,导致我认为我以某种方式滥用了事件队列,尽管我不确定这是我的两个问题的根源......
有任何想法吗?
import tkinter as tk
from PIL import Image, ImageTk
KATA_CHART = "../assets/kata_chart.png"
HIRA_CHART = "../assets/hira_chart.png"
class KanaChart(tk.Frame):
def __init__(self, master, kana_type, **kwargs):
super().__init__(master, **kwargs)
self.build_chart(kana_type)
def _resize_callback(self, *args):
width = self.canvas.winfo_width()
height = self.canvas.winfo_height()
self.img = self.original.resize((width, height))
self.img = ImageTk.PhotoImage(image=self.img)
self.canvas.itemconfig(self.canvas_img, image=self.img)
def build_chart(self, kana_type):
vowels = "AIUEO"
consonants = " KSTNHMYRWNGZDBP"
let_var_dict = {}
for letter in vowels + consonants:
var = tk.BooleanVar()
let_var_dict[letter] = var
for i in range(6):
self.grid_rowconfigure(i, weight=1)
for i in range(17):
self.grid_columnconfigure(i, weight=1)
# build the checkbuttons
for i in range(5):
letter = vowels[i]
row = i + 1
var = let_var_dict[letter]
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=self._checkb_wrapper("r", row, var))
b.grid(row=row, column=0, sticky="nsew")
for i in range(16):
letter = consonants[i]
column = i + 1
var = let_var_dict[letter]
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=self._checkb_wrapper("r", column, var))
b.grid(row=0, column=column, sticky="nsew")
# build the canvas with the chart on it
if kana_type == "hira":
self.original = Image.open(HIRA_CHART)
elif kana_type == "kata":
self.original = Image.open(KATA_CHART)
self.canvas = tk.Canvas(self, bg="black")
self.canvas.grid(row=1, column=1, rowspan=5, columnspan=16,
sticky="nsew")
self.img = ImageTk.PhotoImage(image=self.original)
self.canvas_img = self.canvas.create_image(0, 0, image=self.img,
anchor=tk.NW)
self._resize_callback(None)
self.bind("<Configure>", self._resize_callback)
root = tk.Tk()
chart = KanaChart(root, "kata")
chart.pack(fill=tk.BOTH, expand=1)
root.mainloop()
我已经考虑将我正在使用的图像分割成更小的方块,所以我最终会得到 80 个小图像,我可以匹配到我的小部件网格中的每个单元格,但我假设一个大图像更有效调整超过 80 个小图像的大小。 无论如何,不要认为这会绕过我现在遇到的问题。
由于<Configure>
事件绑定在self
(帧)上,因此执行回调时 canvas 尚未调整大小。 在self.canvas.update()
开头添加 self.canvas.update _resize_callback()
可能会解决问题。
最好在 canvas 上绑定<Configure>
事件。 然后使用事件 object 的宽度和高度属性:
def _resize_callback(self, event):
width, height = event.width, event.height
self.img = self.original.resize((width, height))
self.img = ImageTk.PhotoImage(image=self.img)
self.canvas.itemconfig(self.canvas_img, image=self.img)
同时更新绑定:
def build_chart(self, kana_type):
...
#self._resize_callback(None) # no need to call here
self.canvas.bind("<Configure>", self._resize_callback)
顺便说一句,在build_chart()
的两个 for 循环中,以下代码行存在问题:
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=self._checkb_wrapper("r", row, var))
...
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=self._checkb_wrapper("r", column, var))
它应该是:
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=lambda row=row, var=var: self._checkb_wrapper("r", row, var))
...
b = tk.Checkbutton(self, text=letter, relief=tk.GROOVE, var=var,
command=lambda column=column, var=var: self._checkb_wrapper("r", column, var))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.