pythonmatplotlibpyqt5qt-designeruic

PyQt5: using loadUi with promoted widgets from Qt Designer


Complete newbie to Qt and Qt Designer. I tried following some tutorials online to figure a way to embed matplotlib graph in Qt. Apparently the approach is to use subclass of QWidget which is done by "promoting" the QWidget.

I tried the approach shown in this SE link and this youtube video

Without promoting the QWidget, the *.ui file can be loaded into python without having any issue with the below script.

from PyQt5 import QtWidgets, uic
import sys

class Ui(QtWidgets.QMainWindow):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi('untitled.ui', self)
        self.show()

app = QtWidgets.QApplication(sys.argv)
window = Ui()
app.exec_()

But when I promote the QWidget as below, I get the following error.

enter image description here

Traceback (most recent call last):
  File "C:\Users\user.user\Desktop\pyqt_gui.py", line 11, in <module>
    window = Ui()
  File "C:\Users\user.user\Desktop\pyqt_gui.py", line 7, in __init__
    uic.loadUi('untitled.ui', self)
...
...
...
  File "C:\Users\user.user\Anaconda3\lib\site-packages\PyQt5\uic\Loader\qobjectcreator.py", line 115, in search
    module = __import__(mname, {}, {}, (cls,))
ModuleNotFoundError: No module named 'canvas'

Could someone please shed some light on this ?


Solution

  • It seems the guides you followed don't explain clearly enough how to link the promoted widget to your Canvas class, since your screenshot shows the wrong values. When you first enter the Promoted class name in the Promoted Widgets dialog, Qt Designer will automatically fill in the Header file, so it will end up looking like this:

    screenshpt

    But this is intended to work with C++ projects rather than Python ones, so you need to change "canvas.h" to the import path of the Python module that contains your Canvas class. Thus, if that module is called "canvas.py" and is in the same folder as your "pyqt_gui.py" file, you would simply need to edit the Header file to "camvas" (i.e. without the extension). To fix your existing ui-file, you can re-open the Promoted Widgets dialog and then double-click the current header-file value to edit it (and then also make sure you save the changes afterwards):

    screenshot

    This will result in the following line being added to the generated Python module:

    from canvas import Canvas
    

    (If you want to preview this in Qt Designer, you can select Form -> View Python Code in the menu-bar).


    NB: you can enter any valid Python import path as the Header file. So if your custom widget module was in a sub-package called "widgets", you could enter "widgets.canvas" instead. In addition, it's also possible to use relative imports by specifying the base-package via an argument to loadUi. In that scenario, you would enter ".canvas" (note the leading dot) as the Header file, and then call loadUi like this:

    uic.loadUi('untitled.ui', self, package='widgets')