3 Stimmen

wxPython: Befehl asynchron ausführen, stdout im Textwidget anzeigen

Ich bin auf der Suche nach dem wxPython-Äquivalent zu meiner Antwort für Tcl/Tk-Beispiele? . Konkret möchte ich ein Beispiel dafür sehen, wie man mehrere Schaltflächen erstellt, von denen jede einen externen Befehl ausführt, wenn sie angeklickt wird. Während der Prozess ausgeführt wird, möchte ich die Ausgabe zu einem scrollbaren wxPython Widget gehen.

Während der Prozess läuft, sollte die GUI nicht blockiert werden. Nehmen wir zum Beispiel an, dass eine der Schaltflächen eine Entwicklungsaufgabe wie die Erstellung oder Ausführung von Unit-Tests auslöst.

7voto

FogleBird Punkte 69852

Hier sehen Sie ein vollständiges Arbeitsbeispiel.

import wx
import functools
import threading
import subprocess
import time

class Frame(wx.Frame):
    def __init__(self):
        super(Frame, self).__init__(None, -1, 'Threading Example')
        # add some buttons and a text control
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        for i in range(3):
            name = 'Button %d' % (i+1)
            button = wx.Button(panel, -1, name)
            func = functools.partial(self.on_button, button=name)
            button.Bind(wx.EVT_BUTTON, func)
            sizer.Add(button, 0, wx.ALL, 5)
        text = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.text = text
        sizer.Add(text, 1, wx.EXPAND|wx.ALL, 5)
        panel.SetSizer(sizer)
    def on_button(self, event, button):
        # create a new thread when a button is pressed
        thread = threading.Thread(target=self.run, args=(button,))
        thread.setDaemon(True)
        thread.start()
    def on_text(self, text):
        self.text.AppendText(text)
    def run(self, button):
        cmd = ['ls', '-lta']
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        for line in proc.stdout:
            wx.CallAfter(self.on_text, line)

if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = Frame()
    frame.Show()
    app.MainLoop()

0voto

kgiannakakis Punkte 100768

Starten Sie einen Thread, wenn eine Schaltfläche angeklickt wird:

try:
    r = threading.Thread(target=self.mycallback)
    r.setDaemon(1)
    r.start()
except:
    print "Error starting thread"
    return False

Verwenden Sie wx.PostEvent und wx.lib.newevent, um Nachrichten aus den Callbacks an den Hauptthread zu senden.

Diese Link kann hilfreich sein.

0voto

Jim Carroll Punkte 2300

Bryan, versuchen Sie Folgendes:

import subprocess, sys

def doit(cmd):
    #print cmd
    out = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).stdout
    return out.read()

Wenn also die Schaltfläche gedrückt wird, wird der Befehl mit dem Unterprozessmodul ausgeführt, und Sie erhalten die Ausgabe als Zeichenkette. Sie können ihn dem Wert eines Text Controls zuweisen, um ihn anzuzeigen. Möglicherweise müssen Sie out.readfully() oder mehrmals lesen, um den Text nach und nach anzuzeigen.

Wenn Ihnen die Schaltfläche und das Textfeld nicht bekannt vorkommen, werfen Sie einen kurzen Blick auf die wxPython-Demo wird Ihnen genau zeigen, was Sie tun müssen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X