J'ai vraiment du mal à comprendre comment utiliser Threads dans PyQt. J'ai fait un exemple simple de ce que je voudrais faire dans mon interface utilisateur. Dans le code que vous pouvez voir ci-dessous, je veux que l'utilisateur entre un ticker boursier (vous pouvez entrer "bby", "goog" ou "v" par exemple) et tracer la valeur du stock sur une certaine période. La chose est dans un Ui plus complexe ou pendant une longue période de temps, l'interface utilisateur gèle pendant que l'intrigue est mise à jour. J'ai donc fait une classe "Plotter" qui met à jour le tracé quand il reçoit un certain signal (surcharger Qthread.run n'était apparemment pas le bon chemin you're doing it wrong). Je voudrais faire ce "Plotter" courir dans un autre fil que le principal.Comment utiliser un Qthread pour mettre à jour une figure Matplotlib avec PyQt?
Dès que je décommente les lignes de fil, le programme cesse de fonctionner. J'ai essayé de déplacer le lancement du nouveau thread et aussi le "connecter" mais rien ne fonctionne. Je pense que je ne comprends pas bien comment Qthread fonctionne même après avoir lu le documentation et en regardant les exemples sur le site Web Qt.
Si vous en savez quelque chose, cela aiderait beaucoup! (Je travaille avec Python 3.5 et 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_())
Votre code n'est pas sécurisé aux discussions. Vous ne pouvez pas effectuer d'appels matplotlib (ou Qt GUI) à partir d'un thread secondaire. Vous pouvez récupérer les données dans un thread, mais vous devrez le renvoyer au thread principal pour le traçage en émettant un signal personnalisé (donc renvoyez les données pour le traçage plutôt que l'objet des axes que vous renvoyez maintenant) –