Reputation: 473
I'm experiencing pretty bad tearing while scrolling around in Tkinter. My code so far is a bit complex, so I'll try to explain it by words: I'm using a scrollable Canvas which has a grid of Text elements. Basically, it's a scrollable table. Using the Text widget is important, I'll have to do some text highlighting later so each cell in the table should really be a Text widget.
It looks like this while scrolling:
It is just 30 rows with 5 columns, so 150 text widgets in a canvas, and the tearing looks pretty bad. I thought it would be able to handle this. Is there maybe some "magic" one-liner fix for this, maybe a different theme or something trivial?
EDIT
I have now conjured a solution with just a single tk.Text widget which is impersonating a table. Here is the code.
import tkinter as tk
import random
def insert_values():
global text
# clear first
text.delete(1.0, tk.END)
pad_right = 1
columns = [{"width":20},
{"width":15},
{"width":40},
{"width":20},
{"width":30}]
text.tag_configure("white", background="white")
text.tag_configure("separator", background="SystemButtonFace")
text.tag_configure("highlight_something", background="blue")
text.tag_configure("underline", underline=True, underlinefg='black')
current_line_number_digit = 1
current_line_number = str(current_line_number_digit)
lines_written = 0
while lines_written < 40:
current_left_sum = 0
# insert white background tags for columns and separators
for col_index, column in enumerate(columns):
value_to_write = "Line " + str(lines_written) + ". " + random.sample(["wooo", "eeeee", "meeeoooowww", "too loooooooooong foooooooor thiiiiiiiiiiiiissssss haha"], 1)[0]
if len(value_to_write) >= column["width"]:
value_to_write = value_to_write[0:column["width"]]
else:
value_to_write = value_to_write + " "*(column["width"]-len(value_to_write))
text.insert(current_line_number + "." + str(current_left_sum), value_to_write)
text.tag_add("white", current_line_number + "." + str(current_left_sum), current_line_number + "." + str(current_left_sum+column["width"]))
text.tag_add("underline", current_line_number + "." + str(current_left_sum), current_line_number + "." + str(current_left_sum+column["width"]))
# add tag if needed
if col_index == 2:
text.tag_add("highlight_something", current_line_number + "." + str(current_left_sum+3), current_line_number + "." + str(current_left_sum+12))
current_left_sum+=column["width"]
if col_index != len(columns)-1:
text.insert(current_line_number + "." + str(current_left_sum), " "*pad_right)
text.tag_add("separator", current_line_number + "." + str(current_left_sum), current_line_number + "." + str(current_left_sum+pad_right))
current_left_sum+=pad_right
lines_written+=1
# put a new line before the end
if lines_written < 40:
text.insert(tk.END, "\n")
current_line_number_digit+=1
current_line_number = str(current_line_number_digit)
return
root = tk.Tk()
root.geometry("1200x800")
global text
text = tk.Text(root, width=129, font=("Consolas", 12), background="SystemButtonFace", spacing1=10) ## MUST BE FIXED SIZED FONT!!!! (MONOSIZED FONT)
text.grid(row=0, column=0, padx=5, pady=10)
text.bind("<Key>", lambda e: "break")
vscrollbar = tk.Scrollbar(root, command=text.yview)
vscrollbar.grid(row=0, column=1, sticky='ns')
text["yscrollcommand"] = vscrollbar.set
hscrollbar = tk.Scrollbar(root, command=text.xview, orient='horizontal')
hscrollbar.grid(row=1, column=0, sticky='ew')
text["xscrollcommand"] = hscrollbar.set
button = tk.Button(root, command=insert_values, width=20, text="Insert something")
button.grid(row=2, column=0)
print(root.cget("bg"))
root.mainloop()
This does seem to scroll without stuttering. I can't really figure out how to make a pretty vertical border for the column, for horizontal I have underlining. So I put a layer between, it appears a bit too thick compared to the underline.
Also, there seems to be an issue that when I select a text, it turns invisible if I use white background. I hope there is maybe an option for that.
Upvotes: 0
Views: 66