按钮从子进程PYGTK停止/取消progressBar

时间:2013-12-24 11:59:04

标签: python progress-bar pygtk

我一直在尝试将取消按钮添加到进度条en pygtk但现在可以获得功能。它的功能是执行和脚本,输出中的每一行都计算它并添加到progressBar中。我的问题是如何取消该子进程,有没有办法?

def stop(self, widget):
    print "cancelar"
    os.killpg(self.p.pid, signal.SIGTERM) #=> not working
    self.p.kill() #=> not working


count = 0
command = "script.sh"
self.p = subprocess.Popen(command, shell=True, bufsize=0, stdout=subprocess.PIPE, universal_newlines=True)


for line in iter(self.p.stdout.readline, ""):
    count = count + 1

    while gtk.events_pending():
        gtk.mainiteration()
        gobject.timeout_add(1000, self.update)
        porcentaje = float(count) / float(1400)
        print porcentaje
        self.progress.set_text(str(int(porcentaje * 100)) + "%")
        self.progress.set_fraction(porcentaje)

1 个答案:

答案 0 :(得分:4)

以下示例应该执行您要求的所有操作(希望如此),它会在两个textview中打印长时间运行命令的输出,在stdout的顶部和stderr中打印。

您可以使用停止按钮终止进程,进度将停止脉冲。

与此同时,UI不应该在没有使用线程的情况下冻结,它也应该在Windows上工作(不太确定,但我很有信心)但是你必须在其他方面改变'du'。< / p>

它使用GTK3,所以带有内省的pygobject(你也应该使用它......)但是如果你真的想要使用PyGTK,它应该非常简单易用。

from gi.repository import Gtk, GLib
import os, signal

class MySpawned(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.set_default_size(600,600)

        vb = Gtk.VBox(False, 5)

        self.tw_out = Gtk.TextView()

        sw = Gtk.ScrolledWindow()
        vb.pack_start(sw, True, True, 0)
        sw.add(self.tw_out)

        self.tw_err = Gtk.TextView()

        sw = Gtk.ScrolledWindow()
        vb.pack_start(sw, True, True, 0)
        sw.add(self.tw_err)

        self.progress = Gtk.ProgressBar()
        vb.pack_start(self.progress, False, True, 0)

        bt = Gtk.Button('Run')
        bt.connect('clicked', self.process)
        vb.pack_start(bt, False, False, 0)

        bt = Gtk.Button('Stop')
        bt.connect('clicked', self.kill)
        vb.pack_start(bt, False, False, 0)

        self.add(vb)
        self.set_size_request(200, 300)
        self.connect('delete-event', Gtk.main_quit)
        self.show_all()

    def run(self):
        Gtk.main()

    def update_progress(self, data=None):
        self.progress.pulse()
        return True

    def kill(self, widget, data=None):
        os.kill(self.pid, signal.SIGTERM)

    def process(self, widget, data=None):
        params = ['du', '--si', '/']

        def scroll_to_end(textview):
            i = textview.props.buffer.get_end_iter()
            mark = textview.props.buffer.get_insert()
            textview.props.buffer.place_cursor(i)
            textview.scroll_to_mark(mark, 0.0, True, 0.0, 1.0)

        def write_to_textview(io, condition, tw):
            if condition is GLib.IO_HUP:
                GLib.source_remove(self.source_id_out)
                GLib.source_remove(self.source_id_err)
                return False

            line = io.readline()
            tw.props.buffer.insert_at_cursor(line)
            scroll_to_end(tw)

            while Gtk.events_pending():
                Gtk.main_iteration_do(False)

            return True

        self.pid, stdin, stdout, stderr = GLib.spawn_async(params,
            flags=GLib.SpawnFlags.SEARCH_PATH|GLib.SpawnFlags.DO_NOT_REAP_CHILD,                                       
            standard_output=True,
            standard_error=True)

        self.progress.set_text('Running du --si')

        io = GLib.IOChannel(stdout)
        err = GLib.IOChannel(stderr)

        self.source_id_out = io.add_watch(GLib.IO_IN|GLib.IO_HUP,
                                 write_to_textview,
                                 self.tw_out,
                                 priority=GLib.PRIORITY_HIGH)

        self.source_id_err = err.add_watch(GLib.IO_IN|GLib.IO_HUP,
                                 write_to_textview,
                                 self.tw_err,
                                 priority=GLib.PRIORITY_HIGH)

        timeout_id = GLib.timeout_add(100, self.update_progress)

        def closure_func(pid, status, data):
            GLib.spawn_close_pid(pid)
            GLib.source_remove(timeout_id)
            self.progress.set_fraction(0.0)

        GLib.child_watch_add(self.pid, closure_func, None)

if __name__ == '__main__':
    s = MySpawned()
    s.run()