Home > OS >  strange behaviour of pyplotlib upper menubar
strange behaviour of pyplotlib upper menubar

Time:08-05

I am willing to integrate a matplotlib figure into a GUI designed with pyqt5: I wrote the code above:

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import random

class Ui_MainWindow(QMainWindow):

    def setupUi(self, MainWindow):



        self.vbox = QtWidgets.QVBoxLayout()
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1056, 600)
        self.vbox2 = MainWindow.layout()

        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.lineEdit_x = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_x.setGeometry(QtCore.QRect(550, 430, 40, 20))
        self.lineEdit_x.setObjectName("lineEdit_x")
        self.lineEdit_x.setText(str(1))
        self.lineEdit_y = QtWidgets.QLineEdit(self.centralwidget)
        self.lineEdit_y.setGeometry(QtCore.QRect(595, 430, 40, 20))
        self.lineEdit_y.setObjectName("lineEdit_y")
        self.lineEdit_y.setText(str(1))
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(490, 430, 66, 13))
        self.label_3.setObjectName("label_3")

        self.figure = plt.figure()#figsize=(40, 10), dpi=18)
        self.canvas = FigureCanvas(self.figure)
        #self.canvas.mpl_connect("button_release_event", self.on_release)
        self.canvas.mpl_connect("button_press_event", self.on_press)
        self.canvas.setGeometry(QtCore.QRect(0,30, 400, 400))

        self.toolbar = NavigationToolbar(self.canvas,  self)
        self.vbox2.addWidget(self.toolbar)
        self.vbox2.addWidget(self.canvas)
        self.plot()




        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1056, 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 plot(self):
        data = [random.random() for i in range(23)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-', linewidth=0.5)
        ax.set_title('PyQt Matplotlib Example')
        self.canvas.draw()
    def on_press(self, event):
        self.lineEdit_x.setText(str(event.x))
        self.lineEdit_y.setText(str(event.y))

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

        self.label_3.setText(_translate("MainWindow", "Center (x,y)"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

enter image description here

as one can see I have 2 issues:

  1. the menu bar is detached from the figure and reduced
  2. the axes are smaller than the figure field. so can someone please check my code to address these two issues with minimum modifications thanks

CodePudding user response:

There are many issues with your code, and most of them are caused by the fact that you're editing a pyuic file, which is considered a bad practice, and one of the many reasons of that consideration is that the class pyuic provides is often being used in the wrong way, like in this case.

First of all, you're creating instances for both QMainWindow and Ui_MainWindow, which already inherits from QMainWindow, so the first one is completely pointless.

Then, you're trying to access the main window layout, but that's also wrong, as QMainWindow has its own private layout. The only proper way to add widgets to a main window is using the provided API, and, in your case:

  • setCentralWidget() to set the central widget, which is the main content of the window, and set its layout to which the actual widgets are being added;
  • addToolBar() to add tool bars;

So, this is a proper rewriting of your expected result.

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(1056, 600)

        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.canvas.mpl_connect('button_press_event', self.on_press)

        self.toolbar = NavigationToolbar(self.canvas, self)
        self.addToolBar(self.toolbar)

        self.label = QtWidgets.QLabel('Center (x,y)')

        self.lineEdit_x = QtWidgets.QLineEdit()
        self.lineEdit_x.setText(str(1))

        self.lineEdit_y = QtWidgets.QLineEdit()
        self.lineEdit_y.setText(str(1))

        central = QtWidgets.QWidget(self)
        self.setCentralWidget(central)

        mainLayout = QtWidgets.QVBoxLayout(central)

        mainLayout.addWidget(self.canvas)

        bottomLayout = QtWidgets.QHBoxLayout()
        mainLayout.addLayout(bottomLayout)
        bottomLayout.addWidget(self.label)
        bottomLayout.addWidget(self.lineEdit_x)
        bottomLayout.addWidget(self.lineEdit_y)

        self.plot()


    def plot(self):
        data = [random.random() for i in range(23)]
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-', linewidth=0.5)
        ax.set_title('PyQt Matplotlib Example')
        self.canvas.draw()

    def on_press(self, event):
        self.lineEdit_x.setText(str(event.x))
        self.lineEdit_y.setText(str(event.y))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())

Note that if you still want to use Designer, then keep in mind that:

  • as said above, you should not edit the pyuic generated file (but, instead, follow the official guidelines about using Designer;
  • add the canvas by code, or use a promoted widget (do some research on the subject);
  • always use layout managers for all widgets;
  • Related