我真的很难理解如何在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)调用。你可以在一个线程中获取数据,但是你需要通过发送一个自定义信号将它发送回主线程进行绘图(所以返回绘图数据而不是你现在返回的轴对象) –