我在python中创建脚本,它与bash合作。当我设置所有搜索选项并按下查找按钮时,我想显示带有progress bar
的弹出窗口,当搜索完成时,该窗口会消失。我按popup window
打开popup.show()
,直到我关闭弹出窗口才执行任何功能。那么如何解决这个问题呢?
在控制器类中:
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)
进度栏类:
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
答案 0 :(得分:1)
[解决] 应在每个小部件更新后添加此代码
while gtk.events_pending():
gtk.main_iteration()
答案 1 :(得分:1)
无论如何,这个问题看起来很有意思,但是从外面看很难看到你想要什么,或者你的程序是如何运作的。我整理了一个最小的代码,你可以如何制作一个弹出窗口。
我使用subprocessing
组合bash命令和threading
组合gui。
此代码中需要注意的重要事项:
由于threading
与gtk
结合使用,我们必须使用gobject.threads_init()
不在线程中的函数快速执行并将控制权返回给gtk.main
- 循环
搜索按钮在取消激活时被调用而不是堆叠子进程。
这是代码:
#!/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()