Tkinter:在初始化期间获取实际 canvas 大小(包括 "sticky" 自动拉伸)

Tkinter: Get actual canvas size during init (including auto-stretching by "sticky")

我试图在程序初始化期间将一些文本置于 canvas 的中心。但是,在这种情况下,winfo_width/height 对我来说 return 不是正确的值,因此我无法使用 Canvas 方法 create_text() 正确放置文本,因为我无法计算正确的中心位置。我只能得到正确的尺寸 post-init,如果我在按钮回调中查询尺寸。

如何解决这个问题?这是代码:

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

class GUI:
    def __init__(self):
        # root window of the whole program
        self.root = Tk()
        self.root.minsize(800, 600)

        # canvas/viewport for displaying the image and drawing vectors on it
        self.viewport = Canvas(self.root, bd=2, relief='ridge', highlightthickness=0)

        # define master buttons for audio preview, render to file and clear all vectors
        btn_preview = Button(self.root, text='Preview', command=self.Preview)

        # layout managing
        self.viewport.grid(columnspan=3, padx=5, pady=5, sticky=N+S+W+E)
        btn_preview.grid(row=1, padx=85, pady=10, ipadx=5, ipady=5, sticky=W)

        # position text on canvas to notify user he can load the image by clicking it
        self.viewport.update_idletasks()
        textpos = (self.viewport.winfo_width(),self.viewport.winfo_height())
        print(textpos)
        self.viewport.create_text(textpos[0] / 2, textpos[1] / 2, text="Click here to load an image!", justify='center', font='arial 20 bold')

        # weights of rows and columns
        self.root.rowconfigure(0, weight=1)
        self.root.columnconfigure(0, weight=1)

    def Preview(self, event=None):
        textpos = (self.viewport.winfo_width(),self.viewport.winfo_height())
        print(textpos)

if __name__ == '__main__':
    mainwindow = GUI()
    mainloop()

比较 return 在初始化时编辑的尺寸与单击“预览”按钮后的尺寸。他们是不同的!

OK哈哈,我查了下this answer终于解决了。我需要将 <Configure> 事件绑定到 canvas,并定义一个在 window 调整大小时执行操作的函数。现在可以使用了!

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

class GUI:
    textid = 0

    def __init__(self):
        # root window of the whole program
        self.root = Tk()
        self.root.minsize(800, 600)

        # canvas/viewport for displaying the image and drawing vectors on it
        self.viewport = Canvas(self.root, bd=2, relief='ridge', highlightthickness=0)

        # define master buttons for audio preview, render to file and clear all vectors
        btn_preview = Button(self.root, text='Preview', command=self.Preview)

        # layout managing
        self.viewport.grid(columnspan=3, padx=5, pady=5, sticky=N+S+W+E)
        btn_preview.grid(row=1, padx=85, pady=10, ipadx=5, ipady=5, sticky=W)

        # weights of rows and columns
        self.root.rowconfigure(0, weight=1)
        self.root.columnconfigure(0, weight=1)

        # bind mouse actions for the canvas
        self.viewport.bind('<Configure>', self.ResizeCanvas)

    def Preview(self, event=None):
        textpos = (self.viewport.winfo_width(),self.viewport.winfo_height())
        print(textpos)

    def ResizeCanvas(self, event):
        if self.textid != 0:
            event.widget.delete('openfiletext')
        # position text on canvas to notify user he can load the image by clicking it
        textpos = (self.viewport.winfo_width(), self.viewport.winfo_height())
        self.textid = self.viewport.create_text(textpos[0] / 2, textpos[1] / 2, text="Click here to load an image!", justify='center', font='arial 20 bold', tag='openfiletext')


if __name__ == '__main__':
    mainwindow = GUI()
    mainloop()