I have created a frame that holds a specialized text widget. In my app I have a button to change the color mode from light to dark and vice versa. everything works quite well with the color mode change except the specialized text widget. I have narrowed down the problem and have found that it is the width=134, height=30
that is causing the problem. No idea why though. Any ideas?
Code to reproduce problem:
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()
CodePudding user response:
I figured out the solution; if we remove the width and height from the main part it keeps its size because of the else statement but gets rid of the bug.
Code:
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()
It seems that because it is inputting the width and height from kwargs that it alters the width and height variables to have a problem but I can't be quite sure.