Reputation: 3
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
Upvotes: 0
Views: 472
Reputation: 243897
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_()
Upvotes: 1