#python #user-interface #crash #pyqt
#python #пользовательский интерфейс #сбой #pyqt
Вопрос:
Я искал неприятную ошибку сбоя при выходе из моего приложения PyQt https://github.com/chipmuenk/pyfda уже больше года и только что случайно нашли его: следующий фрагмент кода
self.cmbResponseType = QtGui.QComboBox(self)
self.cmbFilterType = QtGui.QComboBox(self)
self.cmbDesignMethod = QtGui.QComboBox(self)
spacer = QtGui.QSpacerItem(1, 0, QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Fixed)
layHFilWdg = QtGui.QHBoxLayout() # container for filter subwidgets
layHFilWdg.addWidget(self.cmbResponseType)
layHFilWdg.addItem(spacer)
layHFilWdg.addWidget(self.cmbFilterType)
layHFilWdg.addItem(spacer)
layHFilWdg.addWidget(self.cmbDesignMethod)
помещает три поля со списком в поле горизонтальной компоновки с переменным интервалом между ними.
Ошибка исчезает (больше не происходит сбоя при выходе), когда я комментирую одну из двух layHFilWdg.addItem(spacer)
инструкций. Я использую python 2.7 … 3.5 и PyQt 4.8.
У меня в приложении много виджетов с вкладками (а также много других ошибок), и я работал в потоке разработки, который каким-то образом слишком долго подавлял ошибку, вот почему это заняло у меня так много времени. То, что сбой происходит только тогда, когда холст matplotlib был создан в совершенно не связанном подвиджете, — это просто еще одна странность, из-за которой я долгое время лаял не на то дерево …
У кого-нибудь есть идея, в чем проблема с приведенным выше кодом?
Ответ №1:
Это похоже на типичный случай, когда сборщик мусора Python удаляет объекты в порядке, который Qt не ожидает. Возможно, что добавление разделителя несколько раз в один и тот же макет может привести к тому, что Qt попытается удалить его дважды или удалить, когда его больше нет. Очевидным решением является простое: не делайте этого.
Так что либо каждый раз создавайте новый разделитель:
def spacer():
return QtGui.QSpacerItem(
1, 0, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
...
layHFilWdg.addItem(spacer())
или просто используйте метод макета addStretch()
:
layHFilWdg.addWidget(self.cmbResponseType)
layHFilWdg.addStretch()
Комментарии:
1. Это имеет смысл! Было бы сложно столкнуться с аналогичной ситуацией с другими виджетами, где вы ожидаете другого поведения для каждого экземпляра, но с разделителем…
2. По крайней мере, для QT 4.8.7 макет дважды удаляет разделитель… Иногда трудно уловимая ошибка