我想獲得關於如何在Python的PyGTK中實現進度條的最佳實踐的其他人的意見反饋。Python的PyGTK中進度條的最佳實踐
進度條代表的工作在計算上非常重要。因此,我希望這項工作能夠在一個單獨的過程中完成(從而使操作系統可以在不同的核心上運行它)。我希望能夠開始工作,然後在等待結果的同時繼續使用GUI進行其他任務。
我見過很多人間接提出這個問題,但我還沒有看到任何具體的專家意見。我希望通過提出這個問題,我們將看到一個社區的綜合專業知識。
我想獲得關於如何在Python的PyGTK中實現進度條的最佳實踐的其他人的意見反饋。Python的PyGTK中進度條的最佳實踐
進度條代表的工作在計算上非常重要。因此,我希望這項工作能夠在一個單獨的過程中完成(從而使操作系統可以在不同的核心上運行它)。我希望能夠開始工作,然後在等待結果的同時繼續使用GUI進行其他任務。
我見過很多人間接提出這個問題,但我還沒有看到任何具體的專家意見。我希望通過提出這個問題,我們將看到一個社區的綜合專業知識。
我現在意識到,我沒有足夠的聲望使其成爲社區wiki,所以我希望別人可以將其更改爲wiki狀態。謝謝。
我絕不是一個專家的Python程序員,但我花了一些時間試圖找到一個可接受的解決方案。我希望以下代碼可以作爲本次討論的出發點。
import gobject
import pygtk
pygtk.require('2.0')
import gtk
import multiprocessing
import threading
import time
gtk.gdk.threads_init()
class Listener(gobject.GObject):
__gsignals__ = {
'updated' : (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_FLOAT, gobject.TYPE_STRING)),
'finished': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
())
}
def __init__(self, queue):
gobject.GObject.__init__(self)
self.queue = queue
def go(self):
print "Listener has started"
while True:
# Listen for results on the queue and process them accordingly
data = self.queue.get()
# Check if finished
if data[1]=="finished":
print "Listener is finishing."
self.emit("finished")
return
else:
self.emit('updated', data[0], data[1])
gobject.type_register(Listener)
class Worker():
def __init__(self, queue):
self.queue = queue
def go(self):
print "The worker has started doing some work (counting from 0 to 9)"
for i in range(10):
proportion = (float(i+1))/10
self.queue.put((proportion, "working..."))
time.sleep(0.5)
self.queue.put((1.0, "finished"))
print "The worker has finished."
class Interface:
def __init__(self):
self.process = None
self.progress = gtk.ProgressBar()
button = gtk.Button("Go!")
button.connect("clicked", self.go)
vbox = gtk.VBox(spacing=5)
vbox.pack_start(self.progress)
vbox.pack_start(button)
vbox.show_all()
self.frame = vbox
def main(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_border_width(10)
window.add(self.frame)
window.show()
window.connect("destroy", self.destroy)
gtk.main()
def destroy(self, widget, data=None):
gtk.main_quit()
def callbackDisplay(self, obj, fraction, text, data=None):
self.progress.set_fraction(fraction)
self.progress.set_text(text)
def callbackFinished(self, obj, data=None):
if self.process==None:
raise RuntimeError("No worker process started")
print "all done; joining worker process"
self.process.join()
self.process = None
self.progress.set_fraction(1.0)
self.progress.set_text("done")
def go(self, widget, data=None):
if self.process!=None:
return
print "Creating shared Queue"
queue = multiprocessing.Queue()
print "Creating Worker"
worker = Worker(queue)
print "Creating Listener"
listener = Listener(queue)
listener.connect("updated",self.callbackDisplay)
listener.connect("finished",self.callbackFinished)
print "Starting Worker"
self.process = multiprocessing.Process(target=worker.go, args=())
self.process.start()
print "Starting Listener"
thread = threading.Thread(target=listener.go, args=())
thread.start()
if __name__ == '__main__':
gui = Interface()
gui.main()
一些引用我發現有用的是:
Eep。如果你使用PyGTK的線程,你需要非常小心。使用[GUI鎖定](http://developer.gnome.org/pygtk/stable/gdk-functions.html#function-gdk-lock)即開始主循環。在'gtk.gdk.lock:'裏面。導致UI變化的任何呼叫,包括信號發射,都需要在這樣的一個塊中。在開始主循環之前,你需要調用'gtk.gdk.threads_init()'。 – detly 2011-06-02 01:24:15
它工作得非常好,只是說一些縮進缺少4行,但是很棒的工作! – Victor 2017-07-20 16:22:57
這是更多的堆棧Overflo一個問題W上。即使你要求最好,最好也可以是主觀的,在這種情況下,你實際上解釋了什麼是最適合你的。 – Ziv 2011-06-01 23:05:42