2012-12-01 34 views
5

Tôi đang tạo tập lệnh trong python, hợp tác với bash. Khi tôi đặt tất cả các tùy chọn tìm kiếm và nhấn nút tìm, tôi muốn xuất hiện cửa sổ bật lên với progress bar, biến mất khi tìm kiếm sẽ hoàn tất. Tôi mở popup window bởi popup.show() và không có chức năng nào được thực thi cho đến khi tôi đóng cửa sổ bật lên. Vậy làm thế nào để giải quyết vấn đề này?pygtk đang chạy hai cửa sổ, cửa sổ bật lên và chính

Trong lớp điều khiển:

def search(self, widget): 
    cmd = "find " + self.model.directory + " -name \"" + self.model.name + "\"" + " -perm -" + str(self.model.mode) 
    if self.model.type is not None and self.model.type != '': 
     cmd += " -type " + self.model.type 
    if self.model.owner is not None: 
     cmd += " -user " + self.model.owner 
    if self.model.days is not None: 
     cmd += " -mtime -" + str(self.model.days) 

    self.progress = SearcherProgressBar() 

    output = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 
    out = output.stdout.read().strip() 
    array = string.split(out, '\n') 
    self.list = list() 
    self.progress.label = "sdsds" 
    for value in array: 
     self.add_to_list(value) 

    #self.progress.popup.destroy() # when I uncomment, popup never appears 

    self.view.treestore.clear() 
    self.add_to_tree(self.list, None) 
    self.view.expand_item.set_sensitive(True) 

Trong lớp progressbar:

class SearcherProgressBar: 

def __init__(self): 
    self.popup = gtk.Window(gtk.WINDOW_POPUP) 
    vbox = gtk.VBox() 
    self.popup.add(vbox) 
    self.popup.set_size_request(500,100) 
    self.label = gtk.Label("Searching...") 
    vbox.pack_start(self.label, True, True, 0) 
    self.popup.connect("destroy", self.dest) 
    self.popup.show_all() 


def dest(self, widget, data=None): 
    self.popup.destroy() 
    return False 
+3

Make mã của bạn [SSCCE - Ngắn, khép kín, chính xác (compilable), Ví dụ] (http://sscce.org/). Chúng tôi không thể chạy mã bạn có trong câu hỏi của mình. Chúng chỉ là những phần của ứng dụng của bạn. –

Trả lời

1

[SOLVED] Mã này sẽ được thêm vào sau khi cập nhật mỗi phụ tùng

while gtk.events_pending(): 
     gtk.main_iteration() 
1

Dù sao đi nữa, câu hỏi có vẻ khá thú vị mặc dù nó khó khăn từ bên ngoài để xem những gì bạn muốn hoặc cách chương trình của bạn hoạt động và được thiết kế để hoạt động. Tôi đặt cùng một mã tối thiểu cho cách bạn có thể tạo cửa sổ bật lên.

Tôi sử dụng kết hợp subprocessing cho lệnh bash và threading cho gui.

bit quan trọng cần lưu ý trong mã này:

  • Kể từ threading được sử dụng kết hợp với gtk chúng ta phải sử dụng gobject.threads_init()

  • Các chức năng không có trong đề thi một cách nhanh chóng và trở lại kiểm soát đến gtk.main -loop

  • Nút tìm kiếm bị hủy kích hoạt khi được gọi không để ngăn xếp các quy trình con.

Và đây là đoạn code:

#!/usr/bin/env python 

import gtk 
import threading 
import gobject 
from subprocess import Popen, PIPE 

class SearcherProgressBar(object): 
    """This is the popup with only progress-bar that pulses""" 
    def __init__(self): 
     self._popup = gtk.Window(gtk.WINDOW_POPUP) 
     self._progress = gtk.ProgressBar() 
     self._progress.set_text = gtk.Label("Searching...") 
     self._popup.add(self._progress) 

    def run(self, search, target): 
     """Run spawns a thread so that it can return the process to the 
     main app and so that we can do a little more than just execute 
     a subprocess""" 
     self._popup.show_all() 
     self._thread = threading.Thread(target=self._search, args=(search, target)) 
     self._thread.start() 

     #Adding a callback here makes gtk check every 0.42s if thread is done 
     gobject.timeout_add(420, self._callback) 

    def _search(self, cmd, target): 
     """This is the thread, it makes a subprocess that it communicates with 
     when it is done it calls the target with stdout and stderr as arguments""" 
     p = Popen(cmd, stdout=PIPE, stderr=PIPE) 
     target(*p.communicate()) 

    def _callback(self, *args): 
     """The callback checks if thread is still alive, if so, it pulses 
     return true makes callback continue, while false makes it stop""" 
     if self._thread.is_alive(): 
      self._progress.pulse() 
      return True 
     else: 
      self._popup.destroy() 
      return False 

class App(object): 

    def __init__(self): 

     self._window = gtk.Window() 
     self._window.connect("destroy", self._destroy) 

     vbox = gtk.VBox() 
     self._window.add(vbox) 

     self.button = gtk.Button() 
     self.button.set_label('Pretend to search...') 
     self.button.connect('clicked', self._search) 
     vbox.pack_start(self.button, False, False, 0) 

     entry = gtk.Entry() 
     entry.set_text("This is here to show this gui doesn't freeze...") 
     entry.connect("changed", self._gui_dont_freeze) 
     vbox.pack_start(entry, False, False, 0) 

     self._results = gtk.Label() 
     vbox.pack_start(self._results, False, False, 0) 

     self._gui_never_freeze = gtk.Label("Write in entry while searching...") 
     vbox.pack_start(self._gui_never_freeze, False, False, 0) 

     self._window.show_all() 

    def run(self): 

     gtk.main() 

    def _gui_dont_freeze(self, widget): 

     self._gui_never_freeze.set_text(
      "You've typed: '{0}'".format(widget.get_text())) 

    def _search(self, widget): 
     """Makes sure you can't stack searches by making button 
     insensitive, gets a new popup and runs it. Note that the run 
     function returns quickly and thus this _search function too.""" 
     self.button.set_sensitive(False) 
     self._results.set_text("") 
     popup = SearcherProgressBar() 
     popup.run(['sleep', '10'], self._catch_results) 

    def _catch_results(self, stdout, stderr): 
     """This is where we do something with the output from the subprocess 
     and allow button to be pressed again.""" 
     self.button.set_sensitive(True) 
     self._results.set_text("out: {0}\terr: {1}".format(stdout, stderr)) 

    def _destroy(self, *args): 

     self._window.destroy()   
     gtk.main_quit() 

if __name__ == "__main__": 

     #This is vital for threading in gtk to work correctly 
     gobject.threads_init() 
     a = App() 
     a.run() 
+0

Cảm ơn bạn rất nhiều vì đã trả lời. Tôi đã hoàn thành chương trình của mình với đoạn mã ngắn phía trên bài đăng của bạn, nhưng tôi chắc chắn sẽ phân tích mã của bạn và tôi sẽ tìm hiểu một số chủ đề trong python. – dragon7

Các vấn đề liên quan