Dies ist eine Vereinfachung einer Anwendung, die ich geschrieben habe.PySide-Anwendung stürzt ab, wenn ein neues Widget auf QScrollArea gesetzt wird
Das Hauptfenster der Anwendung hat eine Schaltfläche und ein Kontrollkästchen. Das Kontrollkästchen befindet sich in einer QScrollArea (über ein Widget). Das Kontrollkästchen enthält eine Zahl, die angibt, wie oft dieses Kontrollkästchen erstellt wurde. Durch Klicken auf die Schaltfläche wird ein Dialogfeld mit einer Schaltfläche zum Aktualisieren geöffnet.
Wenn Sie auf die Schaltfläche zum Aktualisieren klicken, wird ein neues Widget auf den Bildlaufbereich mit einem neuen Kontrollkästchen gesetzt.
Das Kontrollkästchen hat ein Kontextmenü, das den gleichen Dialog öffnet. Wenn jedoch das Widget erstellt wird, um den Dialog über das Kontextmenü der Checkbox ausgelöst indem die Anwendung abstürzt mit dem folgenden Fehler:
2016-08-03 09:22:00.036 Python[17690:408202] modalSession has been exited prematurely - check for a reentrant call to endModalSession:
Python(17690,0x7fff76dcb300) malloc: * error for object 0x7fff5fbfe2c0: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug
Der Absturz passiert nicht, wenn Sie auf den Button um den Dialog zu öffnen und klicken Sie im Dialogfeld auf Aktualisieren.
Der Absturz passiert auf Mac und Windows. Ich verwende Python 2.7.10 mit pyside 1.2.4
#!/usr/bin/env python
import sys
from itertools import count
from PySide import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.centralwidget = QtGui.QWidget(parent=self)
self.open_diag_btn = QtGui.QPushButton('Open dialog', parent=self)
self.open_diag_btn.clicked.connect(self.open_dialog)
self.scroll_widget = QtGui.QScrollArea(parent=self)
layout = QtGui.QGridLayout(self.centralwidget)
layout.addWidget(self.scroll_widget)
layout.addWidget(self.open_diag_btn)
self.setCentralWidget(self.centralwidget)
self.set_scroll_widget()
def open_dialog(self):
dialog = Dialog(parent=self)
dialog.refresh.connect(self.set_scroll_widget) # Connecting the signal from the dialog to set a new widget to the scroll area
dialog.exec_()
# Even if I call the function here, after the dialog was closed instead of using the signal above the application crashes, but only via the checkbox
# self.set_scroll_widget()
def set_scroll_widget(self):
"""Replacing the widget of the scroll area with a new one.
The checkbox in the layout of the widget has an class instance counter so you can see how many times the checkbox was created."""
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
widget.setLayout(layout)
open_diag_check = RefreshCheckbox(parent=self)
open_diag_check.do_open_dialog.connect(self.open_dialog) # Connecting the signal to open the dialog window
layout.addWidget(open_diag_check)
self.scroll_widget.setWidget(widget)
class RefreshCheckbox(QtGui.QCheckBox):
"""A checkbox class that has a context menu item which emits a signal that eventually opens a dialog window"""
do_open_dialog = QtCore.Signal()
_instance_counter = count(1)
def __init__(self, *args, **kwargs):
super(RefreshCheckbox, self).__init__(unicode(self._instance_counter.next()), *args, **kwargs)
self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
action = QtGui.QAction(self)
action.setText("Open dialog")
action.triggered.connect(self.emit_open_dialog)
self.addAction(action)
def emit_open_dialog(self):
self.do_open_dialog.emit()
class Dialog(QtGui.QDialog):
"""A dialog window with a button that emits a refresh signal when clicked.
This signal is used to call MainWindow.set_scroll_widget()"""
refresh = QtCore.Signal()
def __init__(self, *args, **kwargs):
super(Dialog, self).__init__(*args, **kwargs)
self.refresh_btn = QtGui.QPushButton('Refresh')
self.refresh_btn.clicked.connect(self.do_refresh)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.refresh_btn)
def do_refresh(self):
self.refresh.emit()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mySW = MainWindow()
mySW.show()
mySW.raise_()
app.exec_()
Ersetzen dialog.exec_() mit show() löst den Absturz. Die anderen Kommentare sind ebenfalls nützlich. Vielen Dank! – Nir