Chaco和PyQt无法发出信号



我正试图与Chaco和pyqt合作,为实验室硬件绘制实时数据采集任务。我以前使用的是matplotlib,但它太慢了(我甚至尝试过动画)。当我在pyqt窗口中嵌入matplotlib图时,以下代码运行良好,但使用chaco,当我从线程内部发出更新信号时,不会发生任何事情。如果不使用线程进行模拟采集,则此代码将起作用。我也尝试过使用qthreads,但都无济于事(包括这样的东西:PyQt中的线程和信号问题)。有没有人使用过pyqt+chaco+线程,可以帮助我找到哪里出了问题,或者发生了什么?

import sys
import threading, time
import numpy as np
from enthought.etsconfig.etsconfig import ETSConfig
ETSConfig.toolkit = "qt4"
from enthought.enable.api import Window
from enthought.chaco.api import ArrayPlotData, Plot
from PyQt4 import QtGui, QtCore

class Signals(QtCore.QObject):
    done_collecting = QtCore.pyqtSignal(np.ndarray, np.ndarray)
class PlotWindow(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        x = np.linspace(0,2*np.pi,200)
        y = np.sin(x)
        plotdata = ArrayPlotData(x=x, y=y)
        plot = Plot(plotdata, padding=50, border_visible=True)
        plot.plot(('x', 'y'))
        window = Window(self,-1, component=plot)
        self.setCentralWidget(window.control)
        self.resize(500,500)
        self.pd = plotdata
    def update_display(self, x, y):
        print 'updating'
        self.pd.set_data('x', x)
        self.pd.set_data('y', y)

def run_collection(signal):
    # this is where I would start and stop my hardware,
    # but I will just call the read function myself here
    for i in range(1,10):
        every_n_collected(i, signal)
        time.sleep(0.5)
def every_n_collected(frequency, signal):
    # dummy data to take place of device read
    x = np.linspace(0,2*np.pi,200)
    y = np.sin(x*frequency)
    print 'emitting'
    signal.emit(x, y)
    QtGui.QApplication.processEvents()
def main():
    plt = PlotWindow()
    plt.show()
    QtGui.QApplication.processEvents()
    signals = Signals()
    signals.done_collecting.connect(plt.update_display)
    t = threading.Thread(target=run_collection, args=(signals.done_collecting,))
    t.start()
    t.join()
    QtGui.QApplication.processEvents()    
    # it works without threads though...
    # run_collection(signals.done_collecting)
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    main()

您对主线程(即UI线程)的join调用正在阻塞该线程,并阻止UI处理事件。如果您在主函数中启动了app/GUI事件循环,并在不调用t.join()的情况下等待应用程序关闭,它应该可以正常工作。

这是使用常规Traits/TraitsUI/Chaco应用程序的方法。

import time
import threading
import numpy as np
from traits.etsconfig.etsconfig import ETSConfig
ETSConfig.toolkit = "qt4"
from enable.api import ComponentEditor
from chaco.api import ArrayPlotData, Plot
from traits.api import Event, HasTraits, Instance
from traitsui.api import View, Item
class PlotWindow(HasTraits):
    dataset = Instance(ArrayPlotData)
    plot = Instance(Plot)
    def _dataset_default(self):
        x = np.linspace(0,2*np.pi,200)
        y = np.sin(x)
        plotdata = ArrayPlotData(x=x, y=y)
        return plotdata
    def _plot_default(self):
        plot = Plot(self.dataset, padding=50, border_visible=True)
        plot.plot(('x', 'y'))
        return plot
    def update_display(self, x, y):
        print 'updating', threading.current_thread()
        self.dataset.set_data('x', x)
        self.dataset.set_data('y', y)
    traits_view = View(
        Item('plot', editor=ComponentEditor(size=(400, 400)), show_label=False)
    )
def run_collection(datamodel):
    # this is where I would start and stop my hardware,
    # but I will just call the read function myself here
    for i in range(1,10):
        x = np.linspace(0,2*np.pi,200)
        y = np.sin(x*i)
        datamodel.update_display(x, y)
        time.sleep(0.5)
def main():
    plot = PlotWindow()
    t = threading.Thread(target=run_collection, args=(plot,))
    t.start()
    # Starts the UI and the GUI mainloop
    plot.configure_traits()
    # don't call t.join() as it blocks the current thread...
if __name__ == "__main__":
    main()

相关内容

  • 没有找到相关文章

最新更新