5

私の質問はこれとほとんど同じです: サブプロセス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

Finally I found the solution. After the window construction, you must add :

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

And then after every line insertion in the widget, you must also force a refresh with the same method only on the widget.

# 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 TrueGUI全体の使いやすさをどのようにブロックしないのか疑問に思っていたので、私は尋ねています...そうではありませんか?

疑わしいので、試してみましたが、この例は実際には機能しません。コマンドとして" " のようなものを使用する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 に答える