我已经编写了一个简单的应用程序(见下文),以在ScrolledText上重定向tkinter库的帮助功能数据,类似于
在CLI上打印(help(tkinter.Label))。
我使用了@Bryan Oakley编写的类。
启动后,按“加载”按钮,然后单击左侧树上的声音。
这导致@Bryan Oakley类使用sys.stdout在ScrolledText上写入所选项目的帮助功能数据
sys.stdout.write(帮助)
一切正常,但是即使使用
,我也无法刷新ScrolledText上的数据self.widget.delete('1.0',tk.END)
比使用
sys.stdout.flush()
基本上,当您单击另一个项目时,我无法从ScrolledText中删除所有数据并编写新的sys.stdout
我的做法有什么问题吗?
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()
答案 0 :(得分:1)
在write
语句中添加删除是错误的解决方案,因为您并不总是可以控制发送到write语句的内容。例如,help
实际上可能在您每次调用write
时多次调用。如果是这样,您将只会看到最近一次调用write
的结果。
正确的解决方法是在调用help
之前删除内容。为此,您需要在删除内容之前启用窗口小部件,因为编写的重定向器类使窗口小部件处于禁用状态。
例如,您可以将方法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.write(help(s))
,因为help(s)
仅返回一个空字符串。 help(s)
已将其信息发送到stdout。