[英]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.