我試圖與Chaco和pyqt一起繪製實驗室硬件的實時數據採集任務。我以前使用matplotlib,但它證明太慢了(我甚至嘗試過動畫)。當我在pyqt窗口中嵌入一個matplotlib圖時,下面的代碼工作的很好,但是當使用chaco時,當我從線程內部發出更新信號時沒有任何反應。如果您不使用線程進行模擬採集,此代碼將起作用。我曾嘗試使用qthreads也無濟於事(包括這樣的事情:Threading and Signals problem in PyQt)。有沒有人使用pyqt + chaco +線程來幫助我找到錯誤的地方,或者發生了什麼?Chaco和PyQt發出信號失敗
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()
你永遠不會啓動一個事件循環,並且在信號發出後(除了連接到信號的插槽之外)不要調用'processEvents'。所以信號無法傳遞並不奇怪。如果在't.join()'之後添加'processEvents',會發生什麼? – mata
如果我在t.join()之後添加processEvents,則更新將會執行,但只能在線程完成後立即執行。 – hackyday
你應該在'signal.emit'之後添加它以允許gui更新。將它放在'update_display'中是毫無意義的,因爲除非事件已經發生,否則不會調用它。 – mata