You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:36:04