DoctorEvil
DoctorEvil

Reputation: 473

Tearing in Tkinter while scrolling

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: screenshot


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

Answers (0)

Related Questions