我真的很難理解如何在PyQt中使用線程。我做了一個簡單的例子,說明我想在我的用戶界面中做什麼。在您可以在下面看到的代碼中,我希望用戶輸入股票行情(例如,您可以輸入「bby」,「goog」或「v」),並在特定時間段內繪製股票的價值。事情是在更復雜的用戶界面或很長一段時間的界面凍結,而情節正在更新。所以我做了一個「繪圖儀」課,當它收到一定的信號時更新繪圖(重寫Qthread.run顯然不是正確的方式you're doing it wrong)。我想讓這個「繪圖儀」在另一個線程中運行,而不是主線程。如何使用Qthread使用PyQt更新Matplotlib圖形?
只要取消註釋線程程序,程序就停止工作。我試圖移動新線程的啓動以及「連接」,但沒有任何工作。即使在閱讀了documentation並查看了Qt網站上的示例之後,我認爲我對Qthread的工作原理並不瞭解。
如果有任何你知道如何做到這一點,將會有很大的幫助! (我使用Python 3.5和PyQt5工作)
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from matplotlib.axes._subplots import Axes
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import sys
from datetime import datetime, timedelta
import time
import quandl
class MyMplCanvas(FigureCanvas):
"""Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
send_fig = pyqtSignal(Axes, str, name="send_fig")
def __init__(self, parent=None):
self.fig = Figure()
self.axes = self.fig.add_subplot(111)
# We want the axes cleared every time plot() is called
self.axes.hold(False)
FigureCanvas.__init__(self, self.fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def update_plot(self, axes):
self.axes = axes
self.draw()
class MainWindow(QMainWindow):
send_fig = pyqtSignal(Axes, str, name="send_fig")
def __init__(self):
super().__init__()
self.main_widget = QWidget(self)
self.myplot = MyMplCanvas(self.main_widget)
self.editor = QLineEdit()
self.display = QLabel("Vide")
self.layout = QGridLayout(self.main_widget)
self.layout.addWidget(self.editor)
self.layout.addWidget(self.display)
self.layout.addWidget(self.myplot)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
self.move(500, 500)
self.show()
self.editor.returnPressed.connect(self.updatePlot)
self.plotter = Plotter()
self.send_fig.connect(self.plotter.replot)
self.plotter.return_fig.connect(self.myplot.update_plot)
def updatePlot(self):
ticker = self.editor.text()
self.editor.clear()
self.display.setText(ticker)
# thread = QThread()
# self.plotter.moveToThread(thread)
self.send_fig.emit(self.myplot.axes, ticker)
# thread.start()
class Plotter(QObject):
return_fig = pyqtSignal(Axes)
@pyqtSlot(Axes, str)
def replot(self, axes, ticker): # A slot takes no params
print(ticker)
d = datetime.today() - timedelta(weeks=52) # data from 1week ago
data = quandl.get("YAHOO/"+ticker+".6", start_date=d.strftime("%d-%m-%Y"), end_date=time.strftime("%d-%m-%Y"))
axes.plot(data)
self.return_fig.emit(axes)
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec_())
您的代碼不是線程安全的。您無法從輔助線程調用matplotlib(或任何Qt GUI)調用。你可以在一個線程中獲取數據,但是你需要通過發送一個自定義信號將它發送回主線程進行繪圖(所以返回繪圖數據而不是你現在返回的軸對象) –