Multithreading gtk progressbar没有';matplot事件后,你不能再工作了吗?

Multithreading gtk progressbar没有';matplot事件后,你不能再工作了吗?,multithreading,matplotlib,gtk,pygtk,Multithreading,Matplotlib,Gtk,Pygtk,嗨,我是python和gtk编程新手。 我正在写一个程序来做一些测量。 对于绘制测量,我使用matplotlib。 该程序将具有打开和关闭加热器以及进行测量的功能。 我想使用单独的螺纹进行加热器和测量。 目前,与硬件的通信还没有在这个程序中实现 问题是,当我单击“测量”按钮时,“进度条”不再工作。 我得到一个信息: 0x29b8460处的gtk.ProgressBar对象(在0x0处未初始化) 当我只使用加热按钮时,进度条会继续工作 我做错了什么 这是密码 #!/usr/bin/env pyth

嗨,我是python和gtk编程新手。
我正在写一个程序来做一些测量。 对于绘制测量,我使用matplotlib。
该程序将具有打开和关闭加热器以及进行测量的功能。
我想使用单独的螺纹进行加热器和测量。
目前,与硬件的通信还没有在这个程序中实现

问题是,当我单击“测量”按钮时,“进度条”不再工作。 我得到一个信息:

0x29b8460处的gtk.ProgressBar对象(在0x0处未初始化)

当我只使用加热按钮时,进度条会继续工作

我做错了什么

这是密码

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk
import time
import gobject
import threading
import matplotlib
import numpy as np
from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas

class measure:
    # callback to quit
    def delete_event(self, widget, event, data = None):
        gtk.main_quit()
        return False

    def heater_helper(self, widget, heater, progressbar):
        print "starting heater thread"
        threading.Thread(target=self.heater_cb, args=(widget, heater, progressbar)).start()

    def heater_cb(self, widget, heater, progressbar):
        heaterstring = "6.3"
        heater = eval(heaterstring)
        stap = 1
        j = 0.1
        heatervalue = widget.get_active()
        print heatervalue
        progressbar.set_fraction(0.1)
        while (stap <= 10 ):
            if widget.get_active():
                print widget.get_active()
                fraction = j * stap
                print fraction
                progressbar.set_fraction(fraction)
                stap = stap + 1
                time.sleep(1)
            else:
                stap = 11
                progressbar.set_fraction(0.0)
                break

    def do_measurement_helper(self, widget, fig):
        print " Start measurement thread"
        threading.Thread(target=self.do_measurement, args=(widget, fig)).start()

    def do_measurement(self, widget, fig):
        fig.clear()
        ax = fig.add_subplot(111)
        x = np.arange(0, 5*np.pi, 0.01)
        y = np.sin(x**2)*np.exp(-x)
        ax.plot(x, y)
        fig.canvas.draw()

    def __init__(self):
        # Create new Window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("delete_event", self.delete_event)
        self.window.show()

        mainbox = gtk.HBox(False, 0)
        self.window.add(mainbox)
        mainbox.show()

        leftvbox = gtk.VBox(False, spacing = 10)
        mainbox.pack_start(leftvbox, expand = False, fill = False, padding = 0)
        leftvbox.show()

        rightvbox = gtk.VBox(False, spacing = 10)
        mainbox.pack_start(rightvbox, expand = False, fill = False, padding =0)
        rightvbox.show()

        heaterprogressbar = gtk.ProgressBar()
        leftvbox.pack_start(heaterprogressbar, expand = False, fill = False, padding = 0)
        heaterprogressbar.show()
        heaterbutton = gtk.ToggleButton("Heater")
        leftvbox.pack_start(heaterbutton, expand = True, fill = False, padding = 0)
        heaterbutton.show()
        heaterbutton.connect("toggled", self.heater_helper, heaterbutton, heaterprogressbar)

        fig = matplotlib.figure.Figure(figsize=(5,4), dpi=64)
        canvas = FigureCanvas(fig)
        rightvbox.pack_start(canvas, expand = True, fill = True, padding = 0 )
        canvas.show()
        measurebutton = gtk.Button("Measure")
        rightvbox.pack_start(measurebutton, expand = False, fill = False, padding = 0)
        measurebutton.show()
        measurebutton.connect("clicked", self.do_measurement_helper, fig)

def main():
    gtk.main()
    return(0)

if __name__ == "__main__":
    gtk.gdk.threads_init()
    measure()
    main()
    gtk.gdk.threads_leave()
#/usr/bin/env python
进口pygtk
pygtk.require('2.0')
进口gtk
导入时间
导入gobject
导入线程
导入matplotlib
将numpy作为np导入
从matplotlib.backends.backendgtkagg导入FigureCanvasGTKAgg作为FigureCanvas
等级标准:
#回调退出
def delete_事件(自身、小部件、事件、数据=无):
gtk.main_quit()
返回错误
def加热器辅助程序(自身、小部件、加热器、进度条):
打印“启动加热器螺纹”
threading.Thread(target=self.heater_cb,args=(widget,heater,progressbar)).start()
def加热器_cb(自身、小部件、加热器、进度条):
加热器字符串=“6.3”
加热器=蒸发(加热器管柱)
stap=1
j=0.1
heatervalue=widget.get_active()
打印热值
progressbar.set_分数(0.1)

虽然(stap组合线程、Matplotlib和GTK主循环可能不受支持,并且很难准确调试正在进行的操作。我的建议是不要从线程执行任何GUI调用,而是使用
gobject.idle\u add()对它们进行调度

线程、Matplotlib和GTK主循环可以结合使用,如果您记住以下几点:

  • 我使用了
    gobject.threads_init()
    而不是
    gtk.gdk.threads_init()
    ,gtk.gdk变体在与Matplotlib组合使用时对我不起作用。我想你也可以省略
    gtk.gdk.threads_leave()
  • 正如ptomato提到的,您应该通过调用
    gobject.idle\u add()
    gobject.timeout\u add()函数,让主gtk线程处理与gtk小部件有关的任何事情。
    我通常使用一个助手函数定期更新浮点变量的状态栏:

    def do_measurement(self):
        self.data = []
        self.progress = 0
        self.abort = threading.Event()
        gobject.timeout_add(100, self.update_progressbar)
        for point in some_generator_yielding_100_values():
            if self.abort.is_set():
                break
            self.data.append(point)
            self.progress += 0.01
        self.progress = None
    
    def update_progressbar(self):
        if self.progress is None:
            self.progressbar.set_fraction(0) # reset bar
            return False           # do not run again
        self.progressbar.set_fraction(self.progress)
        return True                # run again after 100ms
    
    def start_measurement(self):
        threading.Thread(target=self.do_measurement).start()
    
    def stop_measurement(self):
        self.abort.set()
    
    当然,您也可以调用
    gobject.idle\u add(self.progressbar.set\u fraction,x)
    异步设置新值
    x