【问题标题】:How can I add pictures from QListview to QGraphicsView? (with Drag Drop)如何将图片从 QListview 添加到 QGraphicsView? (使用拖放)
【发布时间】:2019-09-10 14:28:41
【问题描述】:

首先,我创建 QListview 类。然后,我将项目添加到 QListview。之后,我创建 QGraphicsView 类。我想通过拖放将项目的图片(由 QListview 创建)传输到 QGraphicsView。我有个问题。我无法将项目的图片类转移到类。我的代码是这样的

class PartsList(QListView):
    def __init__(self, parent):
        super().__init__(parent)        
        self.setGridSize(QSize(108, 80))        
        self.partsModel = LibraryModel(self)        
        for i in image_list:
            self.partsModel.appendRow(self.__getPartItem(i))
        self.setModel(self.partsModel)       
        self.setViewMode(self.IconMode)        
        self.setDragDropMode(self.DragOnly)

    def __getPartItem(self, name):
        part = QStandardItem()
        pixmap = QPixmap(name)
        part.setData(pixmap, Qt.DecorationRole)
        part.setText(name)
        part.setEditable(False)
        return part

class LibraryModel(QStandardItemModel):
    def __init__(self, parent=None):
        QStandardItemModel.__init__(self, parent)
        self.setColumnCount(1)

    def mimeTypes(self):
        return ['part/name']

    def DropMimeData(self, idxs):
       mimedata = QMimeData()
       for idx in idxs:
           if idx.isValid():
               txt = self.data(idx, Qt.DisplayRole)
               mimedata.setText(txt)
               mimedata.setData('part/name', txt)
        return mimedata

QGraphicsView

class SchematicView(QGraphicsView):
    def __init__(self, parent):
        self.scene = SchematicScene()
        super().__init__(self.scene, parent)
        self.setSceneRect(0, 0, 1, 1)

   def dragEnterEvent(self, event):
        event.accept()

   def dragMoveEvent(self, event):
        event.accept()


   def dropEvent(self, event):
        pass

【问题讨论】:

    标签: python pyqt pyqt5 qgraphicsview qlistview


    【解决方案1】:

    没有必要创建一个新的mimetype,因为模型默认已经有一个“application/x-qabstractitemmodeldatalist”,所以在这种情况下,我只会在QGraphicsView中创建一个虚拟模型来接收数据,从而能够在 QGraphicsView 中重用它。

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class PartsList(QtWidgets.QListView):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setGridSize(QtCore.QSize(108, 80))
            self.setViewMode(QtWidgets.QListView.IconMode)
            self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)
            self._model = QtGui.QStandardItemModel(self)
            self.setModel(self._model)
            path = QtCore.QStandardPaths.writableLocation(
                QtCore.QStandardPaths.PicturesLocation
            )
            d = QtCore.QDir(path)
            formats = [
                "*.{}".format(fm.data().decode())
                for fm in QtGui.QImageReader.supportedImageFormats()
            ]
            for info in d.entryInfoList(formats, QtCore.QDir.Files):
                part = QtGui.QStandardItem(info.filePath())
                pixmap = QtGui.QPixmap(info.absoluteFilePath())
                part.setData(pixmap, QtCore.Qt.DecorationRole)
                self._model.appendRow(part)
    
    
    class SchematicView(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super().__init__(parent)
            scene = QtWidgets.QGraphicsScene(self)
            self.setScene(scene)
            self.setSceneRect(0, 0, 1, 1)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, event):
            if event.mimeData().hasFormat(
                "application/x-qabstractitemmodeldatalist"
            ):
                event.acceptProposedAction()
    
        def dragMoveEvent(self, event):
            if event.mimeData().hasFormat(
                "application/x-qabstractitemmodeldatalist"
            ):
                event.acceptProposedAction()
    
        def dropEvent(self, event):
            sp = self.mapToScene(event.pos())
            dummy_model = QtGui.QStandardItemModel()
            dummy_model.dropMimeData(
                event.mimeData(), event.dropAction(), 0, 0, QtCore.QModelIndex()
            )
            for r in range(dummy_model.rowCount()):
                for c in range(dummy_model.columnCount()):
                    ix = dummy_model.index(r, c)
                    pixmap = ix.data(QtCore.Qt.DecorationRole)
                    pixmap_item = self.scene().addPixmap(pixmap)
                    pixmap_item.setPos(sp)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QWidget()
        hlay = QtWidgets.QHBoxLayout(w)
        pl = PartsList()
        sv = SchematicView()
        hlay.addWidget(pl)
        hlay.addWidget(sv)
        w.resize(640, 480)
        w.show()
        sys.exit(app.exec_())
    

    如果您仍想继续使用其他 mimetype,在支持 QListView 等模型的视图中,正确的选项是向 mimeData 添加新格式:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class PartsList(QtWidgets.QListView):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setGridSize(QtCore.QSize(108, 80))
            self.setViewMode(QtWidgets.QListView.IconMode)
            self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)
            self._model = LibraryModel(self)
            self.setModel(self._model)
            path = QtCore.QStandardPaths.writableLocation(
                QtCore.QStandardPaths.PicturesLocation
            )
            d = QtCore.QDir(path)
            formats = [
                "*.{}".format(fm.data().decode())
                for fm in QtGui.QImageReader.supportedImageFormats()
            ]
            for info in d.entryInfoList(formats, QtCore.QDir.Files):
                part = self.__getPartItem(info.filePath())
                self._model.appendRow(part)
    
        def __getPartItem(self, name):
            part = QtGui.QStandardItem()
            pixmap = QtGui.QPixmap(name)
            part.setData(pixmap, QtCore.Qt.DecorationRole)
            part.setText(name)
            part.setEditable(False)
            return part
    
    
    class LibraryModel(QtGui.QStandardItemModel):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setColumnCount(1)
    
        def mimeTypes(self):
            return super().mimeTypes() + ["part/name"]
    
        def mimeData(self, indexes):
            data = super().mimeData(indexes)
            encoded = QtCore.QByteArray()
            stream = QtCore.QDataStream(encoded, QtCore.QIODevice.WriteOnly)
            for ix in indexes:
                stream << ix.data(QtCore.Qt.DecorationRole)
            data.setData("part/name", encoded)
            return data
    
    
    class SchematicView(QtWidgets.QGraphicsView):
        def __init__(self, parent=None):
            super().__init__(parent)
            scene = QtWidgets.QGraphicsScene(self)
            self.setScene(scene)
            self.setSceneRect(0, 0, 1, 1)
            self.setAcceptDrops(True)
    
        def dragEnterEvent(self, event):
            if event.mimeData().hasFormat("part/name"):
                event.acceptProposedAction()
    
        def dragMoveEvent(self, event):
            if event.mimeData().hasFormat("part/name"):
                event.acceptProposedAction()
    
        def dropEvent(self, event):
            sp = self.mapToScene(event.pos())
            fmt = "part/name"
            data = event.mimeData()
            if data.hasFormat(fmt):
                encoded = data.data(fmt)
                stream = QtCore.QDataStream(encoded, QtCore.QIODevice.ReadOnly)
                pixmap = QtGui.QPixmap()
                while not stream.atEnd():
                    stream >> pixmap
                    pixmap_item = self.scene().addPixmap(pixmap)
                    pixmap_item.setPos(sp)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = QtWidgets.QWidget()
        hlay = QtWidgets.QHBoxLayout(w)
        pl = PartsList()
        sv = SchematicView()
        hlay.addWidget(pl)
        hlay.addWidget(sv)
        w.resize(640, 480)
        w.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 谢谢大家。你救了我的命:) 还有一件事我想用我选择的文件夹而不是图片。
    • @CemilAlkan 仅将 path = QtCore.QStandardPaths.writableLocation( QtCore.QStandardPaths.PicturesLocation ) 更改为 path = /path/of/your/folder
    • 再次感谢兄弟。不幸的是,我们在土耳其不使用贝宝,但我会为你祈祷:)
    • 我可以返回图片(QListview 到 Qgraphicsview 与拖放),但我想返回图片名称。例如;如果拖放图片是 example.png 我想返回“example”,而不是“example.png”。我想根据名称调用功能。你能帮我吗?
    • @CemilAlkan 在第一种方法中,只需在ix = dummy_model.index(r, c) 之后添加:print (ix.data())
    猜你喜欢
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2014-11-19
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 1970-01-01
    相关资源
    最近更新 更多