如何在ScrolledText

时间:2019-04-08 17:56:33

标签: python tkinter

我已经编写了一个简单的应用程序(见下文),以在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()

enter image description here

1 个答案:

答案 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。