This is a very simple application done with python and qt, where there is an embedded matplotlib plot. I would like to include the standard toolbar (zoom, home, etc.) over the plot. Is it posible? Above there is an example of the code.
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QVBoxLayout, QSizePolicy, QMessageBox, QWidget, QPushButton, QAction, QLineEdit, QLabel
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import random
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.title = 'test'
self.left = 10
self.top = 10
self.width = 1920
self.height = 1080
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
m = PlotCanvas(self, width=10, height=8)
m.move(0,100)
self.statusBar().showMessage('Ready')
mainMenu = self.menuBar()
mainMenu.setNativeMenuBar(False)
fileMenu = mainMenu.addMenu('File')
helpMenu = mainMenu.addMenu('Help')
exitButton = QAction(QIcon('exit24.png'), 'Exit', self)
exitButton.setShortcut('Ctrl+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
self.nameLabel = QLabel(self)
self.nameLabel.setText('Name:')
self.line = QLineEdit(self)
self.nameLabel2 = QLabel(self)
self.nameLabel2.setText('Result')
#self.line2 = QLineEdit(self)
self.line.move(80, 20)
self.line.resize(200, 32)
self.nameLabel.move(20, 20)
#self.line2.move(500, 20)
#self.line2.resize(500, 32)
self.nameLabel2.move(500, 20)
pybutton = QPushButton('Click me', self)
pybutton.clicked.connect(self.clickMethod)
pybutton.resize(100,32)
pybutton.move(50, 50)
def clickMethod(self):
print('Clicked Pyqt button.')
if((self.line.text() == '')):
self.statusBar().showMessage('Not a Number')
else:
print('Number: ' + str(float(self.line.text())*2))
self.statusBar().showMessage('Introduction of a number')
self.nameLabel2.setText(str(float(self.line.text())*2))
class PlotCanvas(FigureCanvas):
def __init__(self, parent=None, width=10, height=8, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
FigureCanvas.__init__(self, fig)
self.setParent(parent)
#self.addWidget(toolbar)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.plot()
def plot(self):
data = [random.random() for i in range(250)]
ax = self.figure.add_subplot(111)
ax.plot(data, 'r-', linewidth = 0.5)
ax.set_title('PyQt Matplotlib Example')
self.draw()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_())
The code has a button, a statusbar, a matplotlib plot and a QlineEdit.
To create a menu for a PyQt5 program we need to use a QMainWindow. This type of menu is visible in many applications and shows right below the window bar. It usually has a file and edit sub menu. The top menu can be created with the method menuBar().
Simple Qt application embedding Matplotlib canvases. This program will work equally well using any Qt binding (PyQt6, PySide6, PyQt5, PySide2). The binding can be selected by setting the QT_API environment variable to the binding name, or by first importing it.
To create a menu, we create a menubar we call . menuBar() on the QMainWindow. We add a menu on our menu bar by calling . addMenu() , passing in the name of the menu.
To create a NavigationToolbar
you must pass the canvas and a parent, but since these are going to be together, it is advisable to create a widget as shown below:
class WidgetPlot(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
self.setLayout(QVBoxLayout())
self.canvas = PlotCanvas(self, width=10, height=8)
self.toolbar = NavigationToolbar(self.canvas, self)
self.layout().addWidget(self.toolbar)
self.layout().addWidget(self.canvas)
and then I would change m = PlotCanvas(self, width = 10, height = 8)
to m = WidgetPlot(self)
, that would solve your problem.
Plus:
To have an appropriate order it is advisable to use layouts, in the following code I show the same code with layouts:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QAction, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QSpacerItem, QSizePolicy, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import QSize
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import random
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.title = 'test'
self.left = 10
self.top = 10
self.width = 1920
self.height = 1080
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.statusBar().showMessage('Ready')
mainMenu = self.menuBar()
mainMenu.setNativeMenuBar(False)
fileMenu = mainMenu.addMenu('File')
helpMenu = mainMenu.addMenu('Help')
exitButton = QAction(QIcon('exit24.png'), 'Exit', self)
exitButton.setShortcut('Ctrl+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
widget = QWidget(self)
self.setCentralWidget(widget)
vlay = QVBoxLayout(widget)
hlay = QHBoxLayout()
vlay.addLayout(hlay)
self.nameLabel = QLabel('Name:', self)
self.line = QLineEdit(self)
self.nameLabel2 = QLabel('Result', self)
hlay.addWidget(self.nameLabel)
hlay.addWidget(self.line)
hlay.addWidget(self.nameLabel2)
hlay.addItem(QSpacerItem(1000, 10, QSizePolicy.Expanding))
pybutton = QPushButton('Click me', self)
pybutton.clicked.connect(self.clickMethod)
hlay2 = QHBoxLayout()
hlay2.addWidget(pybutton)
hlay2.addItem(QSpacerItem(1000, 10, QSizePolicy.Expanding))
vlay.addLayout(hlay2)
m = WidgetPlot(self)
vlay.addWidget(m)
def clickMethod(self):
print('Clicked Pyqt button.')
if self.line.text() == '':
self.statusBar().showMessage('Not a Number')
else:
print('Number: {}'.format(float(self.line.text())*2))
self.statusBar().showMessage('Introduction of a number')
self.nameLabel2.setText(str(float(self.line.text())*2))
class WidgetPlot(QWidget):
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
self.setLayout(QVBoxLayout())
self.canvas = PlotCanvas(self, width=10, height=8)
self.toolbar = NavigationToolbar(self.canvas, self)
self.layout().addWidget(self.toolbar)
self.layout().addWidget(self.canvas)
class PlotCanvas(FigureCanvas):
def __init__(self, parent=None, width=10, height=8, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.plot()
def plot(self):
data = [random.random() for i in range(250)]
ax = self.figure.add_subplot(111)
ax.plot(data, 'r-', linewidth = 0.5)
ax.set_title('PyQt Matplotlib Example')
self.draw()
if __name__ == "__main__":
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_())
Output:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With