当给定宽度和高度时,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 输入宽度和高度,所以它改变了宽度和高度变量,所以有问题,但我不太确定。
我创建了一个包含专用文本小部件的框架。在我的应用程序中,我有一个按钮可以将颜色模式从浅色更改为深色,反之亦然。除专用文本小部件外,一切都适用于颜色模式更改。我缩小了问题范围,发现是 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 输入宽度和高度,所以它改变了宽度和高度变量,所以有问题,但我不太确定。