Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在ScrolledText上管理sys.stdout_Python_Tkinter - Fatal编程技术网

Python 如何在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'

我编写了一个简单的应用程序,如下所示,在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

我的方法有什么错

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。谢谢你的“帮助”提示。今晚我学到了一些有趣的东西;