2011-05-13 48 views
3

我有一个绘制GUI的类,使用gtk。在PyGTK中,如何使用线程?

点击一个按钮会调用一个方法,该方法将运行一些外部的 程序。

但在此期间GUI可能不会重新绘制。

一个解决方案可能是使用线程。这个example在GUI类外创建线程 ,并在调用gtk.main()之前启动它。

如何在GUI类外部检测按钮单击事件并调用 适当的方法?

+0

更正:链接中的示例没有GUI类。 – 2011-05-13 19:32:54

回答

4

你不需要另一个线程来启动外部程序,你可以使用Gtk的空闲循环。以下是我写的一些程序。它必须读取程序的标准输出以在GUI上显示它的一部分,所以我把它留在那里。变量“job_aborted”绑定到“Abort”按钮,可以提前终止。

class MyWindow ... 

    # here's the button's callback 
    def on_simulate(self, button): 
     self.job_aborted = False 
     args = self.makeargs() # returns a list of command-line args, first is program 
     gobject.idle_add(self.job_monitor(args).next) 


    def job_monitor(self, args): 
     self.state_running() # disable some window controls 
     yield True # allow the UI to refresh 

     # set non-block stdout from the child process 
     p = subprocess.Popen(args, stdout=subprocess.PIPE) 
     fd = p.stdout.fileno() 
     fl = fcntl.fcntl(fd, fcntl.F_GETFL) 
     fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) 

     while True: 

     if self.job_aborted: 
      os.kill(p.pid, signal.SIGTERM) 
      break 

     poll = p.poll() 
     if poll is not None: 
      break 

     try: 
      line = p.stdout.readline() 
      if line: 
       line = line.strip() 
       # update display 

     except IOError: 
      pass 

     yield True 

     self.state_ready() # re-enable controls 
     if self.job_aborted: 
     # user aborted 
     else: 
     # success! 
+1

我会补充说,使用基于事件的循环的重点主要是尽可能避免线程。 – 2011-05-13 20:48:51