0

I have a set of routines that essentially mirror the solution found here, except that I have my plot function in its own class that I import. I do this instead of leaving the code as a method within the MyApp class as the solution has in the given link. I make the code to plot the data in its own file because the actual code is very verbose.

My goal: I am trying to make it such that clicking on the graph will change a label in the GUI.

I've tried researching signals/slots and inheritance, but can't grasp how they can connect or apply when a module load is involved. Keep in mind I'm creating the GUI in PyQtDesigner.

Here is my code

main.py

import sys from PyQt5.QtWidgets import QMainWindow from PyQt5 import QtWidgets from timeseries import plotData import design class MyApp(QMainWindow, design.Ui_MainWindow, plotData): def __init__(self, parent=None): super(self.__class__, self).__init__() self.setupUi(self) self.x = [1,2,3,4,5] self.y = [1,2,3,4,5] # Button click plots the timeseries in the first timeseries plot widget self.pushButton_plotData.clicked.connect(lambda: self.plot()) if __name__ == '__main__': # Create GUI application app = QtWidgets.QApplication(sys.argv) form = MyApp() form.show() app.exec_() 

mplwidget.py

from PyQt5 import QtWidgets from matplotlib.figure import Figure from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas import matplotlib # Ensure using PyQt5 backend matplotlib.use('QT5Agg') # Matplotlib canvas class to create figure class MplCanvas(Canvas): def __init__(self): self.fig = Figure(dpi=100) self.ax = self.fig.add_subplot(111) Canvas.__init__(self, self.fig) Canvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) Canvas.updateGeometry(self) # Call when user clicks in the plot window Canvas.mpl_connect(self, s='button_press_event', func=self.get_coord) def get_coord(self, event): if event.button == 1: # Get the x coordinate of the mouse cursor in data coordinates ix = event.xdata print(ix) # GOAL: Want to be able to execute: # self.textBrowser_X1.setText(str(ix[0])) # where textBrowser_X1 is the name of a line edit widget # Matplotlib widget class MplWidget(QtWidgets.QWidget): def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) # Inherit from QWidget self.canvas = MplCanvas() # Create canvas object self.vbl = QtWidgets.QVBoxLayout() # Set box for plotting self.vbl.addWidget(self.canvas) self.setLayout(self.vbl) 

timeseries.py

 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class plotData(FigureCanvas): def __init__(self, parent=None): super().__init__() def plot(self): self.plotWidget.canvas.ax.plot(self.x, self.y) self.plotWidget.canvas.draw() 

design.py

from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1216, 379) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton_plotData = QtWidgets.QPushButton(self.centralwidget) self.pushButton_plotData.setGeometry(QtCore.QRect(216, 20, 96, 33)) font = QtGui.QFont() font.setPointSize(14) self.pushButton_plotData.setFont(font) self.pushButton_plotData.setObjectName("pushButton_plotData") self.plotWidget = MplWidget(self.centralwidget) self.plotWidget.setGeometry(QtCore.QRect(20, 75, 1177, 234)) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.plotWidget.sizePolicy().hasHeightForWidth()) self.plotWidget.setSizePolicy(sizePolicy) self.plotWidget.setObjectName("plotWidget") self.textBrowser_X1 = QtWidgets.QTextBrowser(self.centralwidget) self.textBrowser_X1.setGeometry(QtCore.QRect(132, 21, 75, 30)) self.textBrowser_X1.setObjectName("textBrowser_X1") self.label_X1 = QtWidgets.QLabel(self.centralwidget) self.label_X1.setGeometry(QtCore.QRect(25, 22, 170, 25)) font = QtGui.QFont() font.setPointSize(14) self.label_X1.setFont(font) self.label_X1.setObjectName("label_X1") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1216, 21)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton_plotData.setText(_translate("MainWindow", "Plot Data")) self.label_X1.setText(_translate("MainWindow", "X position 1")) from mplwidget import MplWidget 

1 Answer 1

1

I see that there are many redundant things. For example because it is necessary that PlotWidget is a QWidget that only has the canvas if the canvas is a QWidget, another example is the class plotData that inherits unnecessarily from FigureCanvas in addition to doing a redundant task.

Considering the above, the solution is:

mplwidget.py

from PyQt5 import QtWidgets from matplotlib.figure import Figure from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas import matplotlib # Ensure using PyQt5 backend matplotlib.use("QT5Agg") class MplWidget(Canvas): def __init__(self, parent=None): Canvas.__init__(self, Figure(dpi=100)) self.setParent(parent) self.setSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding ) self.updateGeometry() self.ax = self.figure.add_subplot(111) 

main.py

import sys from PyQt5.QtWidgets import QApplication, QMainWindow import design class MyApp(QMainWindow, design.Ui_MainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.setupUi(self) self.x = [1, 2, 3, 4, 5] self.y = [1, 2, 3, 4, 5] self.pushButton_plotData.clicked.connect(self.plot) self.plotWidget.mpl_connect(s="button_press_event", func=self.get_coord) def plot(self): self.plotWidget.ax.plot(self.x, self.y) self.plotWidget.draw() def get_coord(self, event): if event.button == 1: ix = event.xdata self.textBrowser_X1.setText(str(ix)) if __name__ == "__main__": # Create GUI application app = QApplication(sys.argv) form = MyApp() form.show() app.exec_() 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. So am I forced to have the plot method under MyApp? Or can I import it as I had done in my post?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.