gpt4 book ai didi

python - 将新小部件设置为 QScrollArea 时 PySide 应用程序崩溃

转载 作者:太空宇宙 更新时间:2023-11-03 16:18:06 24 4
gpt4 key购买 nike

这是我编写的应用程序的简化版。

应用程序的主窗口有一个按钮和一个复选框。该复选框位于 QScrollArea 内(通过小部件)。该复选框有一个数字,说明该复选框被创建了多少次。单击该按钮将打开一个带有刷新按钮的对话框。

单击刷新按钮将在滚动区域设置一个新的小部件,并带有一个新的复选框。

该复选框有一个上下文菜单,可以打开相同的对话框。但是,当使用由复选框的上下文菜单触发的对话框创建小部件时,应用程序会崩溃并出现以下错误:

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

单击按钮打开对话框并从对话框中单击刷新时不会发生崩溃。

Mac 和 Windows 上都会发生崩溃。我正在使用 Python 2.7.10 和 PySide 1.2.4

Context menu of the checkbox Main Window

#!/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_()

最佳答案

看起来Python正在尝试删除一个不再存在的对象(或其子对象之一) - 但我并不完全清楚是什么导致了这种情况发生。有问题的对象是滚动区域上设置的小部件。如果您明确保留对它的引用:

    def set_scroll_widget(self):
self._old_widget = self.scroll_widget.takeWidget()
...

您的示例将不再转储核心。

我认为使用 exec 运行对话框可能是问题的最直接原因,因为这意味着它将使用自己的事件循环运行(这可能会影响删除的顺序) -相关事件)。通过使用 show 运行对话框,我能够为您的示例找到更好的修复方法:

def open_dialog(self):
dialog = Dialog(parent=self)
dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
dialog.refresh.connect(self.set_scroll_widget)
dialog.setModal(True)
dialog.show()

以这种方式执行操作意味着不再需要保留对先前滚动区域小部件的显式引用。

关于python - 将新小部件设置为 QScrollArea 时 PySide 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38737106/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com