1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import sys
from tkinter import Text, END

class StdoutRedirector:
def __init__(self, text_widget: Text):
self.text_widget = text_widget
self.last_line_start = 0 # 跟踪最后一行的起始位置

def write(self, output: str):
if output.startswith('/r'):
# 去除前缀 '/r'
output = output[2:]

# 删除最后一行内容
if self.last_line_start != 0:
self.text_widget.delete(f"{self.last_line_start}.0", END)

# 插入新内容
self.text_widget.insert(END, output)

# 更新最后一行的起始位置
self.last_line_start = int(self.text_widget.index('end-1c').split('.')[0])
else:
# 正常写入
self.text_widget.insert(END, output)
if output.endswith('\n'):
self.last_line_start = int(self.text_widget.index('end-1c').split('.')[0]) + 1
else:
self.last_line_start = int(self.text_widget.index('end-1c').split('.')[0])

# 滚动到文本组件的末尾
self.text_widget.see(END)

def flush(self):
"""
刷新缓冲区,确保所有数据被立即写出。
对于Tkinter的Text组件来说,这通常意味着确保所有已写入的内容立即显示给用户。
"""
# 在Tkinter的Text组件中,实际上并没有真正的“刷新”概念,
# 因为写入操作是立即可见的。但为了保持接口一致性,我们仍然提供这个方法。
# 如果需要,这里可以添加代码来强制更新GUI。
self.text_widget.update_idletasks() # 强制刷新GUI,确保所有挂起的任务都被处理

# 示例用法
if __name__ == '__main__':
import tkinter as tk

root = tk.Tk()
text = tk.Text(root, wrap='word') # 设置wrap为'word'以防止单词被分割
text.pack(fill=tk.BOTH, expand=True)

# 重定向stdout到text widget
sys.stdout = StdoutRedirector(text)

# 测试
print("这是第一行")
print("/r这是替换后的第一行")
print("这是第二行")

root.mainloop()