标签:python user-interface multithreading gtk
我有这个主线程:
Gui.py
from gi.repository import Gtk, Gdk
import Process
import gobject
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.label = Gtk.Label('idle')
self.box.pack_start(self.label, True, True, 0)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
gobject.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
def working1():
self.label.set_text('working1')
t = Process.Heavy()
t.heavyworks1()
self.label.set_text('idle')
def on_button_clicked(self, widget):
Gdk.threads_enter()
working1()
Gdk.threads_leave()
if __name__ == '__main__':
gui = gui()
这段代码将生成这个gui:
img http://i42.tinypic.com/33nvrx2.png
我有第二个模块可以做逻辑.
Process.py
import threading
class Heavy(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def heavyworks1(self):
#doing heavy works1
#return result
def heavyworks2(self, *param):
#doing heavy works2
#return result
当我执行此操作时,操作正常,但gui变得冻结.怎么做得好?
编辑:
如user4815162342所说,我将我的代码更改为:
from gi.repository import Gtk, Gdk, GLib
import Process
import gobject
import threading
class gui():
def __init__(self):
self.window = Gtk.Window()
self.window.connect('delete-event', Gtk.main_quit)
self.box = Gtk.Box()
self.window.add(self.box)
self.label = Gtk.Label('idle')
self.box.pack_start(self.label, True, True, 0)
self.progressbar = Gtk.ProgressBar()
self.box.pack_start(self.progressbar, True, True, 0)
self.button = Gtk.Button(label='Start')
self.button.connect('clicked', self.on_button_clicked)
self.box.pack_start(self.button, True, True, 0)
self.window.show_all()
gobject.threads_init()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
def init_progress(self, func, arg):
self.label.set_text('working1')
self.worker = threading.Thread(target=func, args=[arg])
self.running = True
gobject.timeout_add(200, self.update_progress)
self.worker.start()
def update_progress(self):
if self.running:
self.progressbar.pulse()
return self.running
def working(self, num):
Process.heavyworks2(num)
gobject.idle_add(self.stop_progress)
def stop_progress(self):
self.running = False
self.worker.join()
self.progressbar.set_fraction(0)
self.label.set_text('idle')
def on_button_clicked(self, widget):
self.init_progress(self.working, 100000)
if __name__ == '__main__':
gui = gui()
使用该代码,程序有时工作但有时会出现此错误.
1.
**
Gtk:ERROR:/build/buildd/gtk+3.0-3.4.2/./gtk/gtktextview.c:3726:gtk_text_view_validate_onscreen: assertion failed: (priv->onscreen_validated)
Aborted (core dumped)
2.
*** glibc detected *** python: free(): invalid next size (fast): 0x09c9f820 ***
3.
Segmentation fault (core dumped)
解决方法:
您实际上并没有启动该线程,只是实例化了一个可用于启动它的对象.完整的解决方案需要仔细分离GUI线程和工作线程之间的职责.你想要做的是以下内容:
>在单独的线程中进行繁重的计算,由GUI代码生成并加入.计算不应该生成自己的线程,也不需要知道线程(当然,除了线程安全之外).
>线程完成后,使用gobject.idle_add()告诉GUI可以撤消进度指示器. (gobject.idle_add是唯一可以安全地从另一个线程调用的GTK函数.)
通过这样的设置,无论计算如何,GUI都保持完全响应并且进度条更新,并且GUI线程保证在计算完成时注意到.关于您当前代码的两点:
>实例化线程.线程而不是继承它.这样你就不必费心去实现run()了.在这两种情况下,您都必须调用thread.start()来启动线程.
>除非你真的知道自己在做什么,否则不要调用threads_enter()和threads_leave().只要记住,只要你从一个线程(你初始化GTK的同一个线程)中调用所有GTK函数,你就可以了.
以下是实现上述建议的概念验证代码:
def working1(self):
self.label.set_text('working1')
self.work_thread = threading.Thread(self.run_thread)
self.running = True
gobject.timeout_add(200, self.update_progress)
self.work_thread.start()
# the GUI thread now returns to the mainloop
# this will get periodically called in the GUI thread
def update_progress(self):
if self.running:
self.progressbar.pulse() # or set_fraction, etc.
return self.running
# this will get run in a separate thread
def run_thread(self):
Process.heavyworks1() # or however you're starting your calculation
gobject.idle_add(self.stop_progress)
# this will get run in the GUI thread when the worker thread is done
def stop_progress(self):
self.running = False
self.work_thread.join()
self.label.set_text('idle')
标签:python,user-interface,multithreading,gtk 来源: https://codeday.me/bug/20190625/1284021.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。