3

How do I fully mimic sys.stdout in a tkinter text widget so that I can use the print() function (mainly the end parameter) to its full capacity? So that I can use print("Hello World", end='\r') to print to the text widget where if I print something else it will overwrite the previously printed text.

class Main:
    def __init__(self):
        self.master = tk.Tk()
        self.output = tk.Text(self.master)
        self.output.pack()
        sys.stdout = self
        self.master.mainloop()

    def write(self, txt):
        self.output.insert(tk.INSERT, str(txt))
        self.output.see('end')

    def flush(self):
        # What do I do here?

Running

print("Hello World", end='\r')
print("Goodbye World", end='\r')

Gives the following in the text widget

Hello World

Goodbye World

But I expect it to show the following instead

Goodbye World

As a bonus question, how would I (re)define the flush functionality of stdout to work with a tkinter text widget?

Ghorich
  • 428
  • 1
  • 4
  • 13
  • 2
    When I was doing something a little similar, I created a `Canvas` and then added text using `create_text` and `delete('all')` to refresh. Also https://stackoverflow.com/questions/27966626/how-to-clear-delete-the-contents-of-a-tkinter-text-widget – Andrew Dec 17 '18 at 13:01
  • 1
    For me, it puts `"Hello World\nGoodbye World\n"` into the text field, at least that's what I get when I copy and inspect the string, but in the textfield itself, the `\n` is rendered as a small musical half-note... might be an encoding problem? (Using `end='\n'` it shows correctly.) – tobias_k Dec 17 '18 at 13:29
  • 1
    For this to work with arbitrary strings you need to clear the line before further output after a `"\r"`, or the end of longer strings will continue to appear when followed by shorter ones. – holdenweb Dec 19 '18 at 13:13

1 Answers1

0

I fixed the problem with the return carriage by updating the write function with the following:

def write(self, txt):
    if '\r' in txt:
        self.return_carriage = True
        return
    if self.return_carriage:
        self.output.delete(tk.INSERT + " linestart", tk.INSERT + " lineend")
        self.return_carriage = False
    self.output.insert(tk.INSERT, str(txt))
    self.output.see('end')

This only solves the problem when using end='\r' in the print() function though. This still does not mimic the full sys.stdout.write functionality.

Ghorich
  • 428
  • 1
  • 4
  • 13