Debugging widgets not appearing in Qt applications

How to figure things out when something goes wrong
Heads up! You've already completed this tutorial.

Christian Schultz wrote

I'm trying to add the PowerBar widget created in the "Custom Widgets" tutorial in a window made in Qt Creator, but it is not appearing. I made a file named "power_bar.py" with the exact content from the tutorial page, and tested it following the tutorial.

Then, I created a new MainWindow form in Qt Creator, following the "Embedding custom widgets from Qt Designer" tutorial, put there a widget, and promoted it to PowerBar from include file power_bar. The ui content can be seen here: https://pastebin.com/v5i2n0Jr

I then compiled the ui to a file named main_window.py, which can be seen here:

python
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(364, 634)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.powerbarWidget = PowerBar(5)
        self.powerbarWidget.setGeometry(QtCore.QRect(30, 40, 291, 541))
        self.powerbarWidget.setObjectName("powerbarWidget")
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

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

I had to edit this file, in the line where it instantiates the PowerBar, I put a number there because by default it instantiates passing self.centralWidget as the parameter. Then I made a file to show the MainWindow, the content can be seen here:

python
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qt import *
import sys
from main_window import Ui_MainWindow

class Window(QMainWindow):

    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

When I run the code, it shows a window, but it doesn't show the widget. If I put a line after the setupUi like: self.ui.powerbarWidget.show() it shows the widget, but it creates another window.

How can I use this widget in a window, like did in the pyqtgraph example?

Over 10,000 developers have bought Create GUI Applications with Python & Qt!
Create GUI Applications with Python & Qt5
Take a look

Downloadable ebook (PDF, ePub) & Complete Source code

Also available from Leanpub and Amazon Paperback

[[ discount.discount_pc ]]% OFF for the next [[ discount.duration ]] [[discount.description ]] with the code [[ discount.coupon_code ]]

Purchasing Power Parity

Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]


Luca

I guess that you see two windows because at the end of the power_bar.py you have an example of usage not protected by an if statement.

python
from power_bar import PowerBar
from PyQt5.Qt import *
import sys

class Window(QMainWindow):

    def __init__(self):
        super().__init__()
        self.powerbarWidget = PowerBar(5)
        self.setCentralWidget(self.powerbarWidget)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

Add the if statement at the end of the power_bar.py:

python
if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    volume = PowerBar()
    volume.show()
    app.exec_()

Else that code will be executed too whenever you import it. The line of code:

python
from power_bar import PowerBar

shows the first window and enter in the first mainloop. When you close that first window the code after the import is executed, showing another window and entering in another mainloop.


Christian Schultz

Hello Luca, thank you for your answer, but I didn't understand what I did wrong. To facilitate a bit I uploaded my code in a zip file to this address: https://gofile.io/d/a5jRAf There you all the files I made. I started creating the main_window.ui, where it have only a main window with a widget, which I promoted to PowerBar and pointing the include file to pwer_bar. The file power_bar is there too, and this file onle have the two classes needed (PowerBar and _Bar), and it have no code outside the classes. I compiled the main_window.ui to main_window.py, and I had to edit this file to be able to instatiate the PowerBar class, and as far as I could understand, this code adds this widget to the main window widget. Then I made the main.py file, which instantiates the MainWindow, and there I put a line with self.ui.powerbarWidget.show(), which shows the widget in another window. If I comment out this file, the main window opens but it shows nothing inside.

So, I still don't understand what I did wrong in this code, so I'm asking if anyone can point what I did wrong.

Thank you


Luca

When you notice something strange for example:

  • You can't see your widget
  • You see your widget in the wrong place
  • You see the widget in another window

always check the parent of that widget because the problem could be over there, in particular if you are not using the Qt designer.

Opening the main_window.py file and looking for the instantiation of the PowerBar widget I see:

python
self.powerbarWidget = PowerBar(5)

The default value for the parent parameter is None, so I've tried to change it in:

python
self.powerbarWidget = PowerBar(5, parent = self.centralWidget)

And remove the line:

python
self.ui.powerbarWidget.show()

from the file main.py.

In this way it works so the problem is somewhere else.

In the Object inspector of the Qt designer you should see the widget as a child of the centralwidget.

I've tried to generate it and it set the parent correctly.

Could you better describe all the steps that you do before the conversion and after it? Do you manually edit the main_window.py?


Martin Fitzpatrick

As you said, it is passing self.centralWidget as the parameter. You can modify the power bar class to accept a parent (I should have done this, will fix). But the reason the window floats is that it isn't contained within a layout (which sets the parent automatically).

nestedwidget|690x156

You can see in the panel that both of these have the red cross through the layout, meaning that there is no layout applied, so the widget won't be contained in the window. If you don't set a parent on it, it will free-float as it's own window. Set a layout on the centralWidget to avoid this.

The working compiled UI -- had to make the change to the steps param as you noted.

python
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(364, 634)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.powerbarWidget = PowerBar(5)
        self.powerbarWidget.setObjectName("powerbarWidget")
        self.horizontalLayout.addWidget(self.powerbarWidget)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

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


Christian Schultz

Thank you Martin for your help, it worked perfectly. I did another try, where I put another widget and promoted it to PowerBar, edited the compiled ui file (changing one widget to have 5 bars and another to 7 bars) and it worked perfectly.

If I may suggest you, you could add this instructions on the tutorial explaining how to include the custom widget in a window with other widgets (buttons, labels) interacting with the custom widget, it would be awesome.

Other thing that would be awesome is a tutorial explaining how to create a composite widget (meaning, a widget made from other widgets), designing this composite in Qt Designer. Your tutorial explains how to do it using only code, and arranging the widgets using only code sometimes is a bit boring. I am (trying) to make a program where I have a "block" of widgets, and this block I will use in other parts of my application. This block is made of some checkboxes, spin boxes and labels. In order to do it (after reading lots of texts and a lot of try and error) I made it to work, where I create a widget in Qt Designer, arrange them the way I want, then I compile them to a py file, then I copy and paste the contets to another class, edit most of the declarations to make them work, and then I can create methods and signals to interact with the composite widget. It worked, but I need to do a lot of work, and probably there is better ways to do it. If you know how to do it and add this information in the tutorial, it would amazing!


Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Debugging widgets not appearing in Qt applications was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt.