1

I'm making a database editor using PySide6. I made a QPushButton to add 2 rows in a QFormLayout. See screenshot 1

Looks good right? That is what it looked like before you click "Add another column". But then I click and instead of making 2 more rows, it moves them to the end See screenshot 2

Here is my code:

def addTableForm(self):
    def addColumnForm():
        layout.addRow(columnNameLabel, columnName)
        layout.addRow(columnTypeLabel, columnType)
    layout = QFormLayout(self)
    widget = QWidget(self)
    tableNameLabel = QLabel(parent=self, text="Enter the table name")
    tableName = QLineEdit(parent=self)
    columnNameLabel = QLabel(parent=self, text="Add a column")
    columnName = QLineEdit(parent=self)
    columnTypeLabel = QLabel(parent=self, text="Enter the type of the column")
    columnType = QLineEdit(parent=self)
    moreColumnsLabel = QLabel(parent=self, text="Add another column")
    moreColumns = QPushButton(parent=self, text="Add another column", clicked=addColumnForm)
    moreColumns.setFixedWidth(200)
    cancel = QPushButton(self, text="Cancel", clicked=self.selectTables)
    confirm = QPushButton(self, text="Confirm")
    layout.addRow(tableNameLabel, tableName)
    addColumnForm()
    layout.addRow(moreColumnsLabel, moreColumns)
    layout.addRow(cancel, confirm)
    widget.setLayout(layout)
    self.setCentralWidget(widget)

The function is inside a MainWindow class, heir to QMainWindow. Can you please help me out? By the way, can you please also give me some styling tips? I don't like the way how all the widgets are crammed together.

Thanks

1 Answer 1

1

Widgets are unique instances, they are not "duplicated" if you try to add them again to a layout.
In fact, you are not adding new widgets, you're just telling the layout to add a row with the given widgets, and since those widgets already are in the layout, the result is that they get removed, and added to "new" rows, which results in shifting them.

What you need is to dynamically create new widgets, and since you're probably going to need their contents, you should keep their references.

A possible implementation could be the following:

def addTableForm(self):
    columnWidgets = []
    def addColumnForm():
        row = layout.rowCount()
        columnName = QLineEdit()
        layout.insertRow(row, "Add a column", columnName)
        columnType = QLineEdit()
        layout.insertRow(row + 1, "Enter the type of the column", columnType)
        columnWidgets.append((columnName, columnType))

    def getColumnData():
        return [(n.text(), t.text()) for n, t in columnWidgets]

    widget = QWidget()
    layout = QFormLayout(widget)
    tableName = QLineEdit()

    moreColumns = QPushButton(text="Add another column", clicked=addColumnForm)
    moreColumns.setFixedWidth(200)

    layout.addRow("Enter the table name", tableName)
    addColumnForm()
    layout.addRow("Add another column", moreColumns)

    cancel = QPushButton("Cancel", clicked=self.selectTables)
    confirm = QPushButton("Confirm")
    confirm.clicked.connect(lambda: self.createTable(tableName.text(), getColumnData()))

    layout.addRow(cancel, confirm)
    widget.setLayout(layout)
    self.setCentralWidget(widget)

Some notes:

  • you should not use QFormLayout(self) if self is a QMainWindow (which doesn't support setting a layout), since the widget argument of a QLayout constructor is the widget on which the layout will be set; you should use the widget that is going to be used as central widget instead;
  • you don't need to always specify the parent for widgets that are going to be added to a layout: the moment you add those widgets, the parent will take their ownership on its own;
  • unless you need to set specific features, it's not necessary to create QLabels for the first column, just use a string;
  • if the first argument of QPushButton is a string, there's no need to use the keyword;
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your solution! It solved most of my problem, but the new widgets appear below the "Cancel" and "Confirm" buttons. Is there any way to fix that? Thanks
I can't fix the post right now. In any case, read the answer and the QFormLayout documentation and you'll find out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.