Python 如何在ScrolledText上管理sys.stdout
我编写了一个简单的应用程序,如下所示,在ScrolledText上重定向tkinter库的帮助函数数据,类似 在cli上打印helptkinter.Label 我使用了一个由@Bryan Oakley编写的类 启动scipt后,按下“加载”按钮,然后单击左树上的语音 这导致@Bryan Oakley类使用sys.stdout在Scrolled文本上写入所选项目的帮助函数数据 sys.stdout.writehelps 所有这些都可以工作,但即使使用 self.widget.delete'1.0',tk.END 比使用 sys.stdout.flush 基本上,当您单击另一项时,我无法从ScrolledText中删除所有数据并写入新的sys.stdout 我的方法有什么错Python 如何在ScrolledText上管理sys.stdout,python,tkinter,Python,Tkinter,我编写了一个简单的应用程序,如下所示,在ScrolledText上重定向tkinter库的帮助函数数据,类似 在cli上打印helptkinter.Label 我使用了一个由@Bryan Oakley编写的类 启动scipt后,按下“加载”按钮,然后单击左树上的语音 这导致@Bryan Oakley类使用sys.stdout在Scrolled文本上写入所选项目的帮助函数数据 sys.stdout.writehelps 所有这些都可以工作,但即使使用 self.widget.delete'1.0'
import sys
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
class TextRedirector(object):
"""Written Bryan Oakley
https://stackoverflow.com/users/7432/bryan-oakley
"""
def __init__(self, widget, tag="stdout"):
self.widget = widget
self.tag = tag
def write(self, str):
#this generate an error
#self.widget.delete('1.0', tk.END)
self.widget.configure(state="normal")
#it works but generete an error
self.widget.insert("end", str, self.tag)
self.widget.configure(state="disabled")
class App(tk.Frame):
def __init__(self,):
super().__init__()
self.master.title("Hello Tkinter ")
self.selected = tk.StringVar()
self.init_ui()
def init_ui(self):
f = tk.Frame()
f1 = tk.Frame(f)
tk.Label(f, textvariable = self.selected).pack()
cols = (["#0",'','w',False,200,200],
["#1",'','w',True,0,0],)
self.Voices = self.get_tree(f1, cols, show="tree")
self.Voices.show="tree"
self.Voices.pack(fill=tk.Y, padx=2, pady=2)
self.Voices.bind("<<TreeviewSelect>>", self.on_selected)
f1.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
f2 = tk.Frame(f)
self.text = ScrolledText(f2)
self.text.pack(side="top", fill="both", expand=True)
self.text.tag_configure("stderr", foreground="#b22222")
sys.stdout = TextRedirector(self.text, "stdout")
sys.stderr = TextRedirector(self.text, "stderr")
f2.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
w = tk.Frame()
tk.Button(w, text="Load", command=self.set_values).pack()
tk.Button(w, text="Close", command=self.on_close).pack()
w.pack(side=tk.RIGHT, fill=tk.Y, expand=0)
f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)
def set_values(self,):
rs = []
for i in dir(tk):
rs.append(i)
for i in rs:
tree = self.Voices.insert("", tk.END, text=i, values=(i,'tree'))
def on_selected(self, evt=None):
selected_item = self.Voices.focus()
d = self.Voices.item(selected_item)
if d['values']:
item = (d['values'][0])
self.selected.set(item)
s = "tkinter.{}".format(item)
#this generate an error
#sys.stdout.flush()
sys.stdout.write(help(s))
def get_tree(self,container, cols, size=None, show=None):
headers = []
for col in cols:
headers.append(col[1])
del headers[0]
if show is not None:
w = ttk.Treeview(container,show=show)
else:
w = ttk.Treeview(container,)
w['columns']=headers
for col in cols:
w.heading(col[0], text=col[1], anchor=col[2],)
w.column(col[0], anchor=col[2], stretch=col[3],minwidth=col[4], width=col[5])
sb = ttk.Scrollbar(container)
sb.configure(command=w.yview)
w.configure(yscrollcommand=sb.set)
w.pack(side=tk.LEFT, fill=tk.BOTH, expand =1)
sb.pack(fill=tk.Y, expand=1)
return w
def on_close(self):
self.master.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()
在write语句中添加delete是错误的解决方案,因为您并不总是能够控制发送到write语句的内容。例如,“帮助”实际上可能会在每次调用时多次调用“编写”。如果是这样,您将只看到最近一次调用write的结果 正确的解决方案是在调用帮助之前删除内容。为此,您需要在删除内容之前启用小部件,因为所编写的重定向器类使小部件处于禁用状态 例如,您可以将方法clear添加到重定向器类,如下所示:
class TextRedirector(object):
...
def clear(self):
self.widget.configure(state="normal")
self.widget.delete("1.0", "end")
self.widget.configure(state="disabled")
然后,您可以在调用帮助之前立即调用它:
def on_selected(self, evt=None):
...
if d['values']:
...
sys.stdout.clear()
help(s)
注意:您不需要执行sys.stdout.writehelp,因为help只返回一个空字符串。“帮助”已将其信息发送到stdout 提示:在尝试删除文本的代码之后,请立即查看代码。很抱歉,我无法访问它,我已尝试在写入函数中添加self.widget.delete1.0,tk.END,在设置状态正常后,如我在上所示,但它不起作用。没有什么不起作用。我陷入了黑暗中…非常感谢Bryan,我已经了解我的下落,我认为必须直接调用小部件的删除功能或调用sys.stdout.flush。谢谢你的“帮助”提示。今晚我学到了一些有趣的东西;