猿问

python tkinter:使文本小部件自动随文本滚动

我已将 STDOUT 重定向到文本小部件。然后我使用线程来运行子进程,通过 poll() 捕获标准输出并打印它(重定向到文本小部件)。


现在我希望小部件随文本小部件自动滚动,以便用户始终可以看到最新的输出。


(文本小部件的唯一用途是显示运行脚本的输出,因此请随意提出替代方案)


class myGui:

  def __init__(self, master=none)

    self.text_Output = tk.Text(frame_Output)

    self.text_Output.config(borderwidth='1', height='10', insertborderwidth='2', relief='ridge')

    self.text_Output.config(width='50')

    # redirect stdout

    redir = RedirectText(self.text_Output)

    sys.stdout = redir


  def runCode:

   self.p = subprocess.Popen(["COMMAND HERE"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True)

    while self.p.poll() is None:

        msg = self.p.stdout.readline().strip()

        if msg:

            print(msg)



class RedirectText(object):

    def __init__(self, text_ctrl):

        """Constructor"""

        self.output = text_ctrl


    def write(self, string):

        self.output.insert(tk.END, string)


心有法竹
浏览 501回答 1
1回答

Helenr

Text有方法see(...)可以在插入新文本后使用。如果你使用see('end')它会滚动到最后。最小的工作示例 - 每次滚动到末尾insert()编辑:我添加了see()用于滚动到顶部 ( see('1.0')) 或末尾 ( see('end')) 的按钮。import tkinter as tkroot = tk.Tk()text = tk.Text(root)text.pack()button_top = tk.Button(root, text="Move to TOP", command=lambda:text.see('1.0'))button_top.pack()button_end = tk.Button(root, text="Move to END", command=lambda:text.see('end'))button_end.pack()# instert to Text and scroll itfor x in range(50):    text.insert('end', str(x) + '\n')    text.see('end')  # move to the end after adding new textroot.mainloop()    编辑:使用类的最小示例RedirectTextimport tkinter as tkimport sysimport datetime# --- classes ---class RedirectText(object):    def __init__(self, text_widget):        """Constructor"""        self.output = text_widget    def write(self, string):        """Add text to the end and scroll to the end"""        self.output.insert('end', string)        self.output.see('end')# --- functions ---def add_time():    """Add current time every 2 seconds"""    print(datetime.datetime.now())    root.after(2000, add_time)# --- main ---root = tk.Tk()text = tk.Text(root)text.pack()button_top = tk.Button(root, text="Move to TOP", command=lambda:text.see('1.0'))button_top.pack()button_end = tk.Button(root, text="Move to END", command=lambda:text.see('end'))button_end.pack()# keep original `stdout` and assing `RedirectText` as `stdout`old_stdout = sys.stdoutsys.stdout = RedirectText(text)# add some datetime at the beginning print('--- TOP ---')for _ in range(50):    print(datetime.datetime.now())# add new datetime every 2 secondsadd_time()# write to console when `print()` and `sys.stdout` redirect to `Text`old_stdout.write('Hello World!\n')      # needs `\n` print('Hello World!', file=old_stdout)  # doesn't need `\n`root.mainloop()    # assign back original `stdout`    sys.stdout = old_stdout顺便说一句:如果您需要在print()重定向到时打印到控制台Textold_stdout.write('Hello World!\n')      # needs `\n` print('Hello World!', file=old_stdout)  # doesn't need `\n`顺便说一句:您也可以使用file=打印而不分配RedirectText给sys.stdoutredirect = RedirectText(text)print('Hello World!', file=redirect)
随时随地看视频慕课网APP

相关分类

Python
我要回答