PyQt/PySide(包装的 C/C++ 对象已被删除)

Posted

技术标签:

【中文标题】PyQt/PySide(包装的 C/C++ 对象已被删除)【英文标题】:PyQt/PySide (wrapped C/C++ object has been deleted) 【发布时间】:2017-07-27 07:34:42 【问题描述】:

如果我运行这段代码:

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

class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.setGeometry(200,200,800,400)
        self.mainWindowWidget = QWidget()
        self.setCentralWidget(self.mainWindowWidget)

        self.mainWindowLayout = QGridLayout()
        self.mainWindowWidget.setLayout(self.mainWindowLayout)

        self.DnD = DragnDrop()
        self.DnD.setAcceptDrops(True)
        self.DnD.setAlignment(Qt.AlignCenter)
        self.DnD.setStyleSheet('''
        QLabel 
        border: 2px solid rgb(0, 0, 0);
        color: rgb(0, 0, 0);
        background-color: rgb(192, 192, 192);
        
        ''')

        self.DnDList = QListWidget()

        self.mainWindowLayout.addWidget(self.DnD, 1, 0)
        self.mainWindowLayout.addWidget(self.DnDList, 2, 0)

class DragnDrop(QLabel):

    def __init__(self):
        QLabel.__init__(self)
        self.setAcceptDrops(True)


    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):

        self.test = event.mimeData().urls()
        MainWindow().DnDList.addItem(str(self.test))

if __name__ == "__main__":

    myApp = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Plastique'))
    mainWindow = MainWindow()
    mainWindow.show()
    myApp.exec_()
    sys.exit(0)

如果我将文件拖放到 QLabel 上,我会收到此运行时错误

RuntimeError: QListWidget 类型的包装 C/C++ 对象已被删除

对不起,如果我的代码示例很弱,但我不是很精通编程。目标是在 qlabel 上放置一个文件并获取它的文件路径,然后将其显示在 qlistwidget 中。

我查看了this 和this 的问题,但未能完全理解问题的真正含义或我该如何解决。

编辑

我喜欢thomasedv的建议,但没有意识到。

我尝试发出自定义信号,但未能成功将其传递给 MainWindow-Class 的函数。

在我编辑的代码中:

    def dropEvent(self, event):

        self.test = event.mimeData().urls()
        MainWindow().DnDList.addItem(str(self.test))

到:

    def dropEvent(self, event):

        self.emit(SIGNAL("sig"), str(event.mimeData().urls()))

但我现在无能为力如何继续将该字符串添加到我的列表中。

【问题讨论】:

如果您将 MainWindow() 替换为 mainWindow,您的程序在 PySide 中运行良好,这是一个相当简单的错误。此外,报告的错误与我使用您的代码得到的错误有点不同。 【参考方案1】:

我可以让它轻松运行(使用 PyQt5,必须导入一些额外的东西,但我想这是 PySide 和 PyQt5 之间的区别),但拖放不起作用,我认为这是你的问题。我认为用字符串发出一个自定义信号(如果你可以像在 PyQt5 中那样在 PySide 中这样做的话)要好得多,然后在你的主窗口类中将它连接到一个函数,它将它添加到你在那里创建的列表中。现在您正在尝试将列表元素添加到 MainWindow().DnDList 中,我认为这与您在 Mainwindow 类中创建的元素不同。

编辑:这里是信号/槽方法的 PyQt5 实现。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class MainWindow(QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()

        self.setGeometry(200,200,800,400)
        self.mainWindowWidget = QWidget()
        self.setCentralWidget(self.mainWindowWidget)

        self.mainWindowLayout = QGridLayout()
        self.mainWindowWidget.setLayout(self.mainWindowLayout)

        self.DnD = DragnDrop()
        self.DnD.linkDropped.connect(self.urlToList)
        self.DnD.setAcceptDrops(True)
        self.DnD.setAlignment(Qt.AlignCenter)
        self.DnD.setStyleSheet('''
        QLabel 
        border: 2px solid rgb(0, 0, 0);
        color: rgb(0, 0, 0);
        background-color: rgb(192, 192, 192);
        
        ''')

        self.DnDList = QListWidget()

        self.mainWindowLayout.addWidget(self.DnD, 1, 0)
        self.mainWindowLayout.addWidget(self.DnDList, 2, 0)

    @pyqtSlot(str)
    def urlToList(self, url):
        self.DnDList.addItem(url)

class DragnDrop(QLabel):

    linkDropped = pyqtSignal(str)

    def __init__(self):
        QLabel.__init__(self)
        self.setAcceptDrops(True)


    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):

        self.test = event.mimeData().urls()

        self.linkDropped.emit(self.test[0].toString())

if __name__ == "__main__":

    myApp = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Plastique'))
    mainWindow = MainWindow()
    mainWindow.show()
    myApp.exec_()
    sys.exit(0)

需要注意的一点,self.test 实际上是一个带有 QUrls 的列表。所以你需要使用 0 索引。如果要支持多个文件的拖放,请遍历列表中的项目,将每个项目转换为字符串并为每个元素发出,如下所示:

for i in self.test:
    self.linkDropped.emit(i.toString()) 

每个 url 都以 file:\\\ 前缀开头,因为我确定它在浏览器中,如果您不想要它,可能需要稍微更改一下:

i.toString()[8:] 

【讨论】:

如果你能看看我编辑的问题就太好了 @Sahelantro 我确实设法从您的帖子中制作了一个工作示例,但这不是在 pyside 中,而是使用 PyQt5 方法,我认为这是不同的。我暂时什么都做不了,但如果在此期间没有人给出答案,我会尽可能地尝试。 @Sahelantro,用代码更新了答案,不确定它是否适用于 PySide,但我希望如此。

以上是关于PyQt/PySide(包装的 C/C++ 对象已被删除)的主要内容,如果未能解决你的问题,请参考以下文章

PyQt / PySide - 小部件的实际大小

从 QTreeWidgetItem 子类 PyQt/PySide 发出信号的替代方法

Python/pyside,pyqt(pyside,pyqt optional): 控制文本选择的函数

PyQT/Pyside Opengl 小部件覆盖

关闭 PyQt 对话框会终止父进程? (PyQt4 / Pyside) 带有示例代码

将 vtkOrientationMarkerWidget 与 QVTKRenderWindowInteractor 一起使用 [PyQt4/PySide]