简体   繁体   中英

PySide crashing when replacing rows in QFormLayout

Using the following code example PySide segfaults when pushing "Add", "Add", "Remove", "Add" and due to some other sequences of interaction.

  • Python: 2.7.6
  • PySide: 1.2.1
  • QtCore: 4.8.5

Code:

from PySide.QtGui import *
from PySide.QtCore import *

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setObjectName('MainWindow')
        self.baseLayout = QWidget(self)
        self.v_layout = QVBoxLayout(self.baseLayout)
        self.setCentralWidget(self.baseLayout)
        self.form_layout = QFormLayout(self.baseLayout)
        self.v_layout.addLayout(self.form_layout)
        self.button_add = QPushButton(self.baseLayout)
        self.button_add.setText("Add")
        self.v_layout.addWidget(self.button_add)
        self.button_del = QPushButton(self.baseLayout)
        self.button_del.setText("Remove")
        self.v_layout.addWidget(self.button_del)
        self.button_add.clicked.connect(self.add)
        self.button_del.clicked.connect(self.remove)

        self.fields = []

    def add_item(self):
        layout = QHBoxLayout(self.parent())
        line = QLineEdit(self.parent())
        slider = QSlider(self.parent())
        layout.addWidget(line)
        layout.addWidget(slider)
        self.fields.append((layout, line, slider))
        self.form_layout.addRow("Test", layout)

    def add(self):
        for i in range(15):
            self.add_item()

    def remove(self):
        for (layout, line, slider) in self.fields:
            line.deleteLater()
            slider.deleteLater()
        while self.form_layout.itemAt(0):
            child = self.form_layout.takeAt(0)
            if child.widget():
                child.widget().deleteLater()
        self.form_layout.update()
        self.fields = []


def main():
    import sys
    app = QApplication(sys.argv)
    frame = MainWindow()
    frame.show()
    app.exec_()

if __name__ == '__main__':
    main()

Is this the correct way of adding compound widgets (in this case a QLineEdit and a QSlider within a QVBoxLayout ) to a form layout? What am I doing wrong?

The correct way of adding "compound widgets" to a QFormLayout is to create a QWidget that will be the parent to that layout.

add_item() should rather look something like this:

def add_item(self):
    widget = QWidget(self.parent())
    layout = QHBoxLayout(widget)
    line = QLineEdit(widget)
    slider = QSlider(widget)
    layout.addWidget(line)
    layout.addWidget(slider)
    self.fields.append((layout, widget, line, slider))
    self.form_layout.addRow("Test", widget)

(And the widget also has to be removed when deleting the fields).

I think you are not creating the layouts in the right way, for example you are trying to set the layout of base_layout two times. Also you can check for count() on a QLayout to see if it has children:

from PySide.QtGui import *
from PySide.QtCore import *

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.baseLayout = QWidget(self)
        self.v_layout = QVBoxLayout(self.baseLayout)
        self.setCentralWidget(self.baseLayout)

        self.form_layout = QFormLayout()
        self.v_layout.addLayout(self.form_layout)

        self.button_add = QPushButton()
        self.button_add.setText("Add")
        self.v_layout.addWidget(self.button_add)

        self.button_del = QPushButton()
        self.button_del.setText("Remove")
        self.v_layout.addWidget(self.button_del)

        self.button_add.clicked.connect(self.add)
        self.button_del.clicked.connect(self.remove)

        self.fields = []

    def add_item(self):
        layout = QHBoxLayout()
        line = QLineEdit()
        slider = QSlider()
        layout.addWidget(line)
        layout.addWidget(slider)
        self.fields.append((layout, line, slider))
        self.form_layout.addRow("Test", layout)

    def add(self):
        for i in range(15):
            self.add_item()

    def remove(self):

        while self.form_layout.count() > 0:
            child = self.form_layout.takeAt(0)
            widget = child.widget()
            if widget:
                widget.deleteLater()

        self.form_layout.update()
        self.fields = []


def main():
    import sys
    app = QApplication(sys.argv)
    frame = MainWindow()
    frame.show()
    app.exec_()

if __name__ == '__main__':
    main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM