Loading A Widget From A .ui File Into A Window Defined By A Separate .ui File
Solution 1:
There are two possible solutions to your issue.
The easiest way is to remove the topPanelWDG
from the main.ui
, and manually add it from code.
from PyQt5 import QtWidgets, uic
# the following line is not necessary, as we can use loadUi in the same way for# both the widget *and* the main window# Ui_MainWindow, QtBaseClass = uic.loadUiType("main.ui")classTopPanel(QtWidgets.QWidget):
def__init__(self):
super(TopPanel, self).__init__()
uic.loadUi("toppanel.ui", self)
classMainWindow(QtWidgets.QMainWindow):
def__init__(self):
super(MainWindow, self).__init__()
uic.loadUi("main.ui", self)
self.topPanelWDG = TopPanel()
self.verticalLayout.addWidget(self.topPanelWDG)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
# there's no need to pass args here, usually they're important only to the app
sys.exit(app.exec_())
Sometimes, though, you can't easily (or don't want to) add a widget to a layout of an UI created from designer from your code. An alternative approach is to use what Qt calls "promoted widgets".
This works by adding a widget to the ui that will be used as an advanced "placeholder" for the actual widget class you're implementing. In this specific situation, it will be a standard QWidget, but if you're subclassing other widgets (buttons, tables, etc) you'll use them, since it will allows you to set their base properties (a label for the button, the headers of the table, etc) directly from Designer, leaving the class code to do only do what you need to implement.
In your case, leave the topPanelWDG
in the main ui file, right click it and select "Promote to". In the "Promoted class name" insert the class name that will be used (TopPanel
), and in the "Header file" field write the file name (including the relative path, if it is in a subdirectory) of the python file that contains the TopPanel
class definition, without the py
extension.
Finally, click "Add" and then "Promote", and save the file.
At this point you only need to add the *args and **kwargs arguments to the custom widget initialization. These are necessary as now it will be Qt's responsibility to create the widget and, since all widgets accept at least an argument (the parent) those arguments will be added when Qt creates them: if the __init__
function does not accept those arguments, python will raise a TypeError
exception because it's receiving unexpected arguments.
from PyQt5 import QtWidgets, uic
import sys
class TopPanel(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super(TopPanel, self).__init__(*args, **kwargs)
uic.loadUi("toppanel.ui", self)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
uic.loadUi("main.ui", self)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
It's also usually a good habit to use separated files for custom widgets, as their code will be loaded every time a promoted widget is added.
This also means that the portion of code that will actually run your program has to be enclosed in the if __name__ == "__main__":
statement, if the custom widget class is in that file; this is a good habit in any case, as whenever a file is imported it's "main indentation code" is always run.
Post a Comment for "Loading A Widget From A .ui File Into A Window Defined By A Separate .ui File"