簡體   English   中英

顯示tkinter小部件中子進程的實時輸出

[英]Display realtime output of a subprocess in a tkinter widget

我的問題與此問題幾乎相同: 顯示子進程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)

“longrunning”bash腳本的輸出是實時捕獲的(出現在控制台中),但Tkinter窗口僅在子進程結束后出現!!

如何在子進程啟動之前顯示窗口並實時更新其內容?

最后我找到了解決方案。 窗口構建后,您必須添加:

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()

這是一個有趣的解決方案。 是否有可能擁有整個工作代碼?

我在問,因為我很奇怪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

這實際上是為此而發明的。

以防其他人正在尋找它......

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)

這里開始

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM