5

我的问题和这个问题几乎一样: Widget to Display subprocess stdout? 但更进一步。

我有以下代码(python2.7):

def btnGoClick(p1):
    params = w.line.get()
    if len(params) == 0:
        return

    # create child window
    win = tk.Toplevel()
    win.title('Bash')
    win.resizable(0, 0)
    # create a frame to be able to attach the scrollbar
    frame = ttk.Frame(win)
    # the Text widget - the size of the widget define the size of the window
    t = tk.Text(frame, width=80, bg="black", fg="green")
    t.pack(side="left", fill="both")
    s = ttk.Scrollbar(frame)
    s.pack(side="right", fill="y")
    # link the text and scrollbar widgets
    s.config(command=t.yview)
    t.config(yscrollcommand=s.set)
    frame.pack()

    process = subprocess.Popen(["<bashscript>", params], shell=False,
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    while True:
        out = process.stdout.readline()
        if out == '' and process.poll() is not None:
            break
        print out
        t.insert(tk.END, out)

“长时间运行” bash 脚本的输出是实时捕获的(出现在控制台中),但 Tkinter 窗口仅在子进程结束后出现!

如何在子流程启动之前显示窗口并实时更新其内容?

4

3 回答 3

4

最后我找到了解决方案。窗口构建后,您必须添加:

frame.pack()
# force drawing of the window
win.update_idletasks()

然后在小部件中插入每一行之后,您还必须仅在小部件上使用相同的方法强制刷新。

# insert the line in the Text widget
t.insert(tk.END, out)
# force widget to display the end of the text (follow the input)
t.see(tk.END)
# force refresh of the widget to be sure that thing are displayed
t.update_idletasks()
于 2013-03-12T16:03:42.647 回答
1

这是一个有趣的解决方案。那有可能拥有整个工作代码吗?

我问是因为我想知道如何while True不阻止整个 GUI 的可用性......不是吗?

正如怀疑的那样,我试过了,这个例子并没有真正起作用。如果您使用类似“ ls -Rf /”的命令作为命令,您将看到 while 循环将使 txt 输出流畅地进行。然而,两个窗口(主要和次要)都会阻塞大量时间。

我怀疑您需要在单独的线程或进程中发送 print txt 部分。或者,如果你使用 pygtk,你可以使用类似的东西

gobject.io_add_watch(self.ep1.stdout,       # file descriptor
                     gobject.IO_IN,         # condition
                     self.write_to_buffer ) # callback

这实际上是为此而发明的。

于 2013-05-30T12:44:11.350 回答
1

以防万一其他人正在寻找它...

log_box_1 = tk.Text(root, borderwidth=3, relief="sunken")

with subprocess.Popen("ls -la", shell=True, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True) as p:
            for line in p.stdout:
                log_box_1.insert(tk.END, line)

这里

于 2019-06-14T19:27:03.183 回答