Python Tkinter如何实现Canvas上按钮和文本自动跟随窗口缩放
解决方案
你可以通过存储元素初始相对比例、动态修改元素属性的方式实现自适应,核心修改点如下:
- 移除了resizer方法中重复创建文本的逻辑,避免多次缩放后元素重叠
- 在初始化阶段存储了窗口基准尺寸、各元素的ID和初始相对比例
- 缩放时按当前窗口与基准窗口的比例,动态调整文本的位置、字体大小,以及按钮的位置、尺寸
- 把原来的全局背景变量改为实例变量,避免被垃圾回收导致背景消失
修改后的完整代码如下:
from tkinter import * from tkinter import font from PIL import Image, ImageTk class GUI: def __init__(self, parent, *args, **kwargs): super(GUI, self).__init__(*args, **kwargs) # 基础窗口设置 self.parent = parent self.parent.title("Mining ETH statistics!") # self.parent.iconbitmap('eth_icon.ico') # 可根据实际路径调整 self.base_width = 600 self.base_height = 530 self.parent.geometry(f'{self.base_width}x{self.base_height}') # 初始化自定义字体,用于文本大小自适应 self.base_font_size = 20 self.custom_font = font.Font(size=self.base_font_size) # 背景设置 self.bg_img = Image.open("eth_background.png") self.img = ImageTk.PhotoImage(self.bg_img.resize((self.base_width, self.base_height), Image.ANTIALIAS)) self.my_canvas = Canvas(self.parent, width=self.base_width, height=self.base_height) self.bg_id = self.my_canvas.create_image(0, 0, image=self.img, anchor='nw') self.my_canvas.pack(fill='both', expand=True) # 存储文本初始比例、创建文本元素 self.text_x_ratio = 300 / self.base_width self.text_y_ratio = 100 / self.base_height self.text_id = self.my_canvas.create_text(300, 100, text="FOO", font=self.custom_font) # 存储Greet按钮初始比例、创建按钮 self.greet_x_ratio = 10 / self.base_width self.greet_y_ratio = 10 / self.base_height self.greet_button = Button(parent, text="Greet", command=self.greet, width=5, height=1) self.greet_window_id = self.my_canvas.create_window(10, 10, anchor="nw", window=self.greet_button) # 存储Close按钮初始比例、创建按钮 self.close_x_ratio = 290 / self.base_width self.close_y_ratio = 500 / self.base_height self.close_button = Button(parent, text="Close", command=parent.quit, width=5, height=1) self.close_window_id = self.my_canvas.create_window(290, 500, anchor="nw", window=self.close_button) def greet(self): print("Greetings!") def resizer(self, e): """背景、文本、按钮自适应缩放""" # 计算缩放比例 width_scale = e.width / self.base_width height_scale = e.height / self.base_height # 更新背景 resized_bg = self.bg_img.resize((e.width, e.height), Image.ANTIALIAS) self.new_bg = ImageTk.PhotoImage(resized_bg) self.my_canvas.itemconfig(self.bg_id, image=self.new_bg) # 更新文本位置和字体大小 new_text_x = self.text_x_ratio * e.width new_text_y = self.text_y_ratio * e.height self.my_canvas.coords(self.text_id, new_text_x, new_text_y) new_font_size = int(self.base_font_size * min(width_scale, height_scale)) self.custom_font.config(size=new_font_size) # 更新Greet按钮位置 new_greet_x = self.greet_x_ratio * e.width new_greet_y = self.greet_y_ratio * e.height self.my_canvas.coords(self.greet_window_id, new_greet_x, new_greet_y) # 如需调整按钮大小可取消下方注释 # self.greet_button.config(width=int(5*width_scale), height=int(1*height_scale)) # 更新Close按钮位置 new_close_x = self.close_x_ratio * e.width new_close_y = self.close_y_ratio * e.height self.my_canvas.coords(self.close_window_id, new_close_x, new_close_y) # 如需调整按钮大小可取消下方注释 # self.close_button.config(width=int(5*width_scale), height=int(1*height_scale)) if __name__ == "__main__": root = Tk() gui = GUI(root) root.bind('<Configure>', gui.resizer) root.mainloop()
如果不需要调整文本字体大小,删除字体相关的代码即可。
内容的提问来源于stack exchange,提问作者HGH
相关产品推荐
相关产品推荐

