Reputation: 1
I am having some trouble with the creation of a GUI using PyQt5.
The final goal is to have a main window from which I can open a sub-window. In the sub-window, I need to be able to create a certain number of couples of line edits.
The position of the line edits must be aligned to 2 upper labels.
I started from what was suggested in this link (PyQT: Add widget after window show). My code was modelled on the answer:
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow
import sys
from Window import Ui_MainWindow
from Subwindow import Ui_Subwindow
class Def_Win(QMainWindow):
def __init__(self):
super(Def_Win, self).__init__()
self.ui = Ui_Subwindow()
self.ui.setupUi(self)
self.ui.Button_1.clicked.connect(self.AddField)
self.num = 1
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.ui.Button_1)
def AddField(self,result):
Text_reg = QtWidgets.QLineEdit("Text 1 of {}".format(self.num))
Text_reg.setGeometry(20, 20 + self.num*20, 30, 16)
Text_reg_2 = QtWidgets.QLineEdit("Text 2 of {}".format(self.num))
Text_reg_2.setGeometry(40, 20 + self.num*20, 30, 16)
self.layout.addWidget(Text_reg)
self.layout.addWidget(Text_reg_2)
self.num += 1
if self.num == 10:
self.ui.Button_1.setEnabled(False)
def MyWin():
app = QApplication(sys.argv)
win = Def_Win()
win.show()
sys.exit(app.exec_())
MyWin()
I can get the sub-window (which is already defined in another file). But I can't seem to create the new line edits. In particular, the original code had:
self.layout = QtWidgets.QVBoxLayout(self.ui.centralwidget)
I had to remove the content of the parentheses because the line edits would pile up one after the other, while I would like to have two columns. By doing so, I can no longer create any new line edit.
Here I attach the Subwindow.py code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Subwindow(object):
def setupUi(self, Subwindow):
Subwindow.setObjectName("Subwindow")
Subwindow.resize(483, 600)
self.centralwidget = QtWidgets.QWidget(Subwindow)
self.centralwidget.setObjectName("centralwidget")
self.label_1 = QtWidgets.QLabel(self.centralwidget)
self.label_1.setGeometry(QtCore.QRect(30, 20, 171, 21))
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(12)
font.setBold(False)
font.setWeight(50)
self.label_1.setFont(font)
self.label_1.setAlignment(QtCore.Qt.AlignCenter)
self.label_1.setObjectName("label_1")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(280, 20, 171, 21))
font = QtGui.QFont()
font.setFamily("Segoe UI")
font.setPointSize(12)
self.label_2.setFont(font)
self.label_2.setAlignment(QtCore.Qt.AlignCenter)
self.label_2.setObjectName("label_2")
self.Button_1 = QtWidgets.QPushButton(self.centralwidget)
self.Button_1.setGeometry(QtCore.QRect(20, 530, 191, 23))
self.Button_1.setObjectName("Button_1")
self.Button_2 = QtWidgets.QPushButton(self.centralwidget)
self.Button_2.setGeometry(QtCore.QRect(380, 530, 75, 23))
self.Button_2.setObjectName("Button_2")
Subwindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(Subwindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 483, 21))
self.menubar.setObjectName("menubar")
Subwindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(Subwindow)
self.statusbar.setObjectName("statusbar")
Subwindow.setStatusBar(self.statusbar)
self.retranslateUi(Subwindow)
QtCore.QMetaObject.connectSlotsByName(Subwindow)
def retranslateUi(self, Subwindow):
_translate = QtCore.QCoreApplication.translate
Subwindow.setWindowTitle(_translate("Subwindow", "MainWindow"))
self.label_1.setText(_translate("Subwindow", "Text 1"))
self.label_2.setText(_translate("Subwindow", "Text 2"))
self.Button_1.setText(_translate("Subwindow", "Add text edit"))
self.Button_2.setText(_translate("Subwindow", "Process"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Subwindow = QtWidgets.QMainWindow()
ui = Ui_Subwindow()
ui.setupUi(Subwindow)
Subwindow.show()
sys.exit(app.exec_())
Upvotes: 0
Views: 98
Reputation: 48489
Unfortunately the user who gave that answer has the terrible habit of just giving the final code without explaining the reason of the original issue nor clarifying the modifications, and this usually leads to people randomly trying to replicate that code without understanding what they do and why.
The main problem with what you want to achieve is that you're not using a layout manager, which allows to properly set the geometries of widgets according to a specified organization (in that answer the user created the layout, but, as said, unfortunately didn't explain how it was done and how).
The best solution is to add the layout directly in Designer (here is a more comprehensive guide).
For simple cases, a grid layout for the whole interface could suffice, but since you're going to create widgets dynamically, it's better to rely on nested structures:
buttonsLayout
; def AddField(self,result):
Text_reg = QtWidgets.QLineEdit("Text 1 of {}".format(self.num))
Text_reg.setGeometry(20, 20 + self.num*20, 30, 16)
Text_reg_2 = QtWidgets.QLineEdit("Text 2 of {}".format(self.num))
Text_reg_2.setGeometry(40, 20 + self.num*20, 30, 16)
rowLayout = QtWidgets.QHBoxLayout()
rowLayout.addWidget(Text_reg)
rowLayout.addWidget(Text_reg_2)
self.ui.buttonsLayout.addLayout(rowLayout)
self.num += 1
if self.num == 10:
self.ui.Button_1.setEnabled(False)
A slightly different alternative is to use a QGridLayout for the "container", but in my experience it offers more drawbacks than benefits when dealing with dynamic layouts, as its management of row/column cells is sometimes erratic, and it doesn't allow "inserting" rows or columns in the existing layout.
A couple of suggestions: instead of creating the self.ui
object, you can just inherit from both QMainWindow and the ui, using class Def_Win(QMainWindow, Ui_Subwindow):
, removing the creation of self.ui
and just calling self.setupUi(self)
. Also, function and variable names should always start with a lower case letter, as only classes and constants should be capitalized.
Upvotes: 1