我不能简单地在循环中调用gtk_progress_bar_set_fraction
,因为在循环结束之前它不会产生任何影响。
如果我使用gtk_main_iteration();
强制main在gtk_progress_bar_set_fraction
的调用中进行迭代,那么它当然有效..但循环过程显着变慢。
在循环处理时,如何更新进度条?
答案 0 :(得分:0)
我用这个例子来了解进步和进步线程
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
'''
Simple example of a PyGTK3 application with a background thread.
'''
import random
import threading
import time
from gi.repository import Gtk, GObject
APP_NAME = 'Threaded GUI Example'
TARGET = 100.0
class WorkerThread(threading.Thread):
'''
The worker thread, which would normally do something more useful.
It is important that the worker thread does not attempt to update the
GUI. Doing so can cause crashes and weird behaviour.
@param delegate the object to be informed of progress being made
'''
def __init__(self, delegate):
threading.Thread.__init__(self)
self.delegate = delegate
self.counter = 0
self.done = False
def run(self):
'''
The work done by the thread.
Overridden from threading.Thread. Sits in a loop until the done
flag is set, updating a counter and sleeping to simulate some work.
'''
while True:
if self.done:
print 'Background thread shutting down cleanly'
break
# This counter is only updated by one thread, so probably
# doesn't need a lock, but it needs thinking about.
self.counter = self.counter + 1 if self.counter < TARGET else 0
# Ask the main thread to update the GUI when it has time.
GObject.idle_add(self.delegate.update_progress)
# Sleep for a little bit ...
time.sleep(random.uniform(0.01, 0.1))
class Main(Gtk.Window):
'''
The main application GUI running in the main thread.
'''
def __init__(self):
Gtk.Window.__init__(self, title=APP_NAME)
self.set_size_request(500, 300)
# Lay out the GUI.
vbox = Gtk.VBox(False, 0)
# Set up a progress bar to show how the worker is progressing.
self.progress_bar = Gtk.ProgressBar()
vbox.pack_start(self.progress_bar, False, False, 0)
# Set up a text view to show the responsiveness of the GUI.
scroller = Gtk.ScrolledWindow()
textview = Gtk.TextView()
textview.get_buffer().set_text(
'The counting is going on in the worker thread with the GUI '\
'handling updates in the idle loop. You can type in the text '\
'view or resize the window and it should be responsive.\n\n'
)
textview.set_wrap_mode(Gtk.WrapMode.WORD)
scroller.add(textview)
vbox.pack_start(scroller, True, True, 0)
self.add(vbox)
self.show_all()
# Connect the destroy event so that we can set the done flag and
# terminate the worker cleanly.
self.connect("destroy", self.on_quit)
# Kick off the background thread.
self.worker = WorkerThread(self)
self.worker.start()
def update_progress(self):
'''
Update the progress bar.
The method called on request in the idle loop to update the GUI. The
worker requests the update using GObject.idle_add()
@return True to repeat indefinitely, False for a single invocation
'''
progress = self.worker.counter / TARGET
self.progress_bar.set_fraction(progress)
self.set_title('{} ({}%)'.format(APP_NAME, progress * 100))
return False
def on_quit(self, widget):
'''
Quit the application
Handler called when the application is about to quit. Set the done
flag so that the worker quits cleanly, then quit.
'''
self.worker.done = True
Gtk.main_quit()
if __name__ == '__main__':
# The background thread will not run concurrently against the main
# thread without the threads_init() call:
GObject.threads_init()
Main()
Gtk.main()