当给定宽度和高度时,Tkinter 框架先收缩然后增长

Tkinter frame shrinks and then grows when width and height is given

我创建了一个包含专用文本小部件的框架。在我的应用程序中,我有一个按钮可以将颜色模式从浅色更改为深色,反之亦然。除专用文本小部件外,一切都适用于颜色模式更改。我缩小了问题范围,发现是 width=134, height=30 导致了问题。不知道为什么。有什么想法吗?

重现问题的代码:

from tkinter import *
class ultra_text(Frame):
    def __init__(self, *args, **kwargs):
        self.window = kwargs.pop("window", None)
        self.color_mode = kwargs.pop("color_mode")
        Frame.__init__(self, *args, **kwargs)
        if "height" and "width" in kwargs:
            self.text = Text(self, height=kwargs["height"], width=kwargs["width"], borderwidth=2, relief=RIDGE, wrap=NONE, undo=True, font=("Courier New bold", 15))
        else:
            self.text = Text(self, font=("Courier New bold", 15), wrap="none", undo=True, borderwidth=2, relief=RIDGE, width=120, height=30)

        self.scrollbar = Scrollbar(self, orient=VERTICAL, command=self.text.yview)
        self.text.configure(yscrollcommand=self.scrollbar.set)


        self.numberLines = TextLineNumbers(self, width=40)
        self.numberLines.attach(self.text)

        self.scrollbar.pack(side=RIGHT, fill=Y)
        self.numberLines.pack(side=LEFT, fill=Y, padx=(5, 0))
        self.text.pack(side=RIGHT, fill=BOTH, expand=True)

        self.text.bind("<Key>", self.onPressDelay)
        self.text.bind("<Button-1>", self.numberLines.redraw)
        self.scrollbar.bind("<Button-1>", self.onScrollPress)
        self.text.bind("<MouseWheel>", self.onPressDelay)

        self.window.bind("<KeyRelease>", self.redraw())

#Place tag_config here

    def change_color(self, new_color):
        if new_color == "Dark":
            bg = "black"
            fg = "white"
        else:
            bg = "white"
            fg = "black"
        self.text.config(bg=bg, fg=fg, insertbackground=fg)
        self.numberLines.config(bg=bg)
    
    def onScrollPress(self, *args):
        self.scrollbar.bind("<B1-Motion>", self.numberLines.redraw)

    def onScrollRelease(self, *args):
        self.scrollbar.unbind("<B1-Motion>", self.numberLines.redraw)

    def onPressDelay(self, *args):
        self.after(2, self.numberLines.redraw)

    def get(self, *args, **kwargs):
        return self.text.get(*args, **kwargs)

    def insert(self, *args, **kwargs):
        return self.text.insert(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.text.delete(*args, **kwargs)

    def index(self, *args, **kwargs):
        return self.text.index(*args, **kwargs)

    def redraw(self):
        self.numberLines.redraw()

class TextLineNumbers(Canvas):
    def __init__(self, *args, **kwargs):
        Canvas.__init__(self, *args, **kwargs, highlightthickness=0)
        self.textwidget = None

    def attach(self, text_widget):
        self.textwidget = text_widget

    def redraw(self, *args):
        '''redraw line numbers'''
        self.delete("all")

        i = self.textwidget.index("@0,0")
        while True :
            dline= self.textwidget.dlineinfo(i)
            if dline is None: break
            y = dline[1]
            linenum = str(i).split(".")[0]
            self.create_text(2, y, anchor="nw", text=linenum, fill="#808090") #606366
            i = self.textwidget.index("%s+1line" % i)
if __name__ == "__main__":
    window = Tk()
    color_mode = "Light"
    window.geometry("%dx%d+0+0" % (window.winfo_screenwidth(), window.winfo_screenheight()))
    my_text = ultra_text(window, window = window, color_mode="Dark", width=134, height=30)#Problem is here <- get rid of ", width=134, height=30" and it works. Keep it and it has the bug. How do I get rid of the bug while keeping the width and height?
    my_text.place(relx=.5, rely=.5, anchor=CENTER)
    def change_color_mode():
        global my_text
        global color_mode
        if color_mode == "Dark":
            color_mode = "Light"
        else:
            color_mode = "Dark"
        if color_mode == "Dark":
            bg = "black"
        else:
            bg = "white"
        my_text.change_color(color_mode) #This part is fine and does the bulk of the color_changing
        my_text.configure(bg=bg)
        change_color_mode_button.config(highlightbackground=bg)
        window.configure(bg=bg)
    change_color_mode_button = Button(window, text="Change Color Mode", command=change_color_mode)
    change_color_mode_button.pack()
    window.mainloop()

我找到了解决办法;如果我们从主要部分中删除宽度和高度,它会因为 else 语句而保持其大小,但会消除错误。

代码:


from tkinter import *
class ultra_text(Frame):
    def __init__(self, *args, **kwargs):
        self.window = kwargs.pop("window", None)
        self.color_mode = kwargs.pop("color_mode")
        Frame.__init__(self, *args, **kwargs)
        if "height" and "width" in kwargs:
            self.text = Text(self, height=kwargs["height"], width=kwargs["width"], borderwidth=2, relief=RIDGE, wrap=NONE, undo=True, font=("Courier New bold", 15))
        else:
            self.text = Text(self, font=("Courier New bold", 15), wrap="none", undo=True, borderwidth=2, relief=RIDGE, width=120, height=30)

        self.scrollbar = Scrollbar(self, orient=VERTICAL, command=self.text.yview)
        self.text.configure(yscrollcommand=self.scrollbar.set)


        self.numberLines = TextLineNumbers(self, width=40)
        self.numberLines.attach(self.text)

        self.scrollbar.pack(side=RIGHT, fill=Y)
        self.numberLines.pack(side=LEFT, fill=Y, padx=(5, 0))
        self.text.pack(side=RIGHT, fill=BOTH, expand=True)

        self.text.bind("<Key>", self.onPressDelay)
        self.text.bind("<Button-1>", self.numberLines.redraw)
        self.scrollbar.bind("<Button-1>", self.onScrollPress)
        self.text.bind("<MouseWheel>", self.onPressDelay)

        self.window.bind("<KeyRelease>", self.redraw())

#Place tag_config here

    def change_color(self, new_color):
        if new_color == "Dark":
            bg = "black"
            fg = "white"
        else:
            bg = "white"
            fg = "black"
        self.text.config(bg=bg, fg=fg, insertbackground=fg)
        self.numberLines.config(bg=bg)
    
    def onScrollPress(self, *args):
        self.scrollbar.bind("<B1-Motion>", self.numberLines.redraw)

    def onScrollRelease(self, *args):
        self.scrollbar.unbind("<B1-Motion>", self.numberLines.redraw)

    def onPressDelay(self, *args):
        self.after(2, self.numberLines.redraw)

    def get(self, *args, **kwargs):
        return self.text.get(*args, **kwargs)

    def insert(self, *args, **kwargs):
        return self.text.insert(*args, **kwargs)

    def delete(self, *args, **kwargs):
        return self.text.delete(*args, **kwargs)

    def index(self, *args, **kwargs):
        return self.text.index(*args, **kwargs)

    def redraw(self):
        self.numberLines.redraw()

class TextLineNumbers(Canvas):
    def __init__(self, *args, **kwargs):
        Canvas.__init__(self, *args, **kwargs, highlightthickness=0)
        self.textwidget = None

    def attach(self, text_widget):
        self.textwidget = text_widget

    def redraw(self, *args):
        '''redraw line numbers'''
        self.delete("all")

        i = self.textwidget.index("@0,0")
        while True :
            dline= self.textwidget.dlineinfo(i)
            if dline is None: break
            y = dline[1]
            linenum = str(i).split(".")[0]
            self.create_text(2, y, anchor="nw", text=linenum, fill="#808090") #606366
            i = self.textwidget.index("%s+1line" % i)

if __name__ == "__main__":
    window = Tk()
    color_mode = "Light"
    window.geometry("%dx%d+0+0" % (window.winfo_screenwidth(), window.winfo_screenheight()))
    my_text = ultra_text(window, window = window, color_mode="Dark")
    my_text.place(relx=.5, rely=.5, anchor=CENTER)
    def change_color_mode():
        global my_text
        global color_mode
        if color_mode == "Dark":
            color_mode = "Light"
        else:
            color_mode = "Dark"
        if color_mode == "Dark":
            bg = "black"
        else:
            bg = "white"
        my_text.change_color(color_mode) #This part is fine and does the bulk of the color_changing
        my_text.configure(bg=bg)
        change_color_mode_button.config(highlightbackground=bg)
        window.configure(bg=bg)
    change_color_mode_button = Button(window, text="Change Color Mode", command=change_color_mode)
    change_color_mode_button.pack()
    window.mainloop()

似乎是因为它从 kwargs 输入宽度和高度,所以它改变了宽度和高度变量,所以有问题,但我不太确定。