如何在pyqt5中复制粘贴Qgraphicsitem?

2024-09-25 18:24:51 发布

您现在位置:Python中文网/ 问答频道 /正文

在场景中复制粘贴QGraphicsitem时遇到问题。 我尝试了以下代码,但它不能正常工作。 如果我尝试粘贴项目,第一个实例就是正确粘贴。对于第二个实例,它删除第一个实例项并粘贴第二个实例。在

到目前为止,我已经尝试在复制操作中获取项目的路径,并将其添加到粘贴操作中的场景中。在

@pos2是我的格子位置

我只想粘贴复制的项目n次,直到新项目被复制。如果我复制粘贴的方式不对,请纠正我。在

from PyQt5.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData, QPointF, QPoint, Qt, QRect,QTimer,QLineF, QEvent,QRectF)
from PyQt5.QtGui import QColor, QDrag, QPainter, QPixmap,QFont,QFontMetrics,QBrush, QLinearGradient, QIcon, QPen, QPainterPath, QTransform,QCursor,QMouseEvent,QClipboard
from PyQt5.QtWidgets import QApplication,QGraphicsTextItem,QGraphicsItemGroup, QSizePolicy, QScrollArea, QPushButton,QLineEdit, QMainWindow,QInputDialog, QGraphicsPathItem,QDialog, QVBoxLayout,QGraphicsItem,QStatusBar,QTextEdit, QAction,QMenu, qApp,QSplitter, QButtonGroup, QToolButton, QFrame, QHBoxLayout, QGraphicsView, QGraphicsItem, QGraphicsPixmapItem, QLabel, QGraphicsScene, QWidget
class GraphicsSceneClass(QGraphicsScene):
    global selectedObjType
    def __init__(self, parent=None):
        super(GraphicsSceneClass, self).__init__(parent)

        self.setSceneRect(0, 0, 1920, 1080)
        self.setItemIndexMethod(QGraphicsScene.NoIndex)
        self.setBackgroundBrush(QBrush(Qt.black))

    def mousePressEvent(self, event):
            sampleTransform = QTransform()
            objectAtMouse = self.itemAt(event.scenePos(), sampleTransform)

            if objectAtMouse and event.button()== Qt.LeftButton:
                objectAtMouse.setSelected(True)

            elif objectAtMouse==None and event.button()==Qt.RightButton:
                self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
    def TargPosForLine(self, position, mode):

        clicked_column = int((position.y() // 16)) * 16
        clicked_row = int((position.x() // 16)) * 16
        if clicked_column < 0:
            clicked_column = 0
        if clicked_row < 0:
            clicked_row = 0
        if(mode == "ForRect"):
            return QRect(clicked_row, clicked_column,16,16)
        elif(mode == "ForLine"):
            return QPointF(clicked_row,clicked_column)
class MainWindow(QMainWindow):
    global selectedObjType
    # global item
    def __init__(self,):
        super(MainWindow, self).__init__()
        self.scene = GraphicsSceneClass()
        MainWindow.obj = self.scene
        self.view = QGraphicsView(self.scene)
        self.view.setMouseTracking(True)
        self.view.setRenderHint(QPainter.HighQualityAntialiasing)
        self.widg = QWidget()
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.addWidget(self.view)
        self.widg.setMouseTracking(True)
        self.widget = QWidget()
        self.widget.setLayout(self.horizontalLayout)
        self.setCentralWidget(self.widget)
        self.obj=None

    def contextMenuEvent(self, event):
        contextMenu = QMenu(self)

        Cutaction = contextMenu.addAction("Cut")
        Coaction = contextMenu.addAction("Copy")
        Paaction = contextMenu.addAction("Paste")
        Propaction = contextMenu.addAction("draw")
        quitAct = contextMenu.addAction("quit")
        action = contextMenu.exec_(self.mapToGlobal(event.pos()))
        if action == quitAct:
            self.close()
        elif action == Propaction:
            painterPath = QPainterPath()

            painterPath.moveTo(10, 50.0)
            painterPath.lineTo(50,50)
            painterPath.lineTo(50,55)
            painterPath.lineTo(10,55)
            gradient = QLinearGradient(1, 1, 1, 5)
            gradient.setColorAt(0, QColor(Qt.gray))
            gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
            gradient.setColorAt(1, QColor(Qt.darkGray))
            painterPath.closeSubpath()

            objectDrop = QGraphicsPathItem()
            objectDrop.setPath(painterPath)
            objectDrop.setBrush(QBrush(gradient))
            self.scene.addItem(objectDrop)
            objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
            objectDrop._type1="line"
            # self.scene.addPath(painterPath)


        elif action == Coaction:
            self.copy()
        elif action == Paaction:
            self.paste()

    def copy(self):
        item = self.selectedItem()
        self.dragObject = item
        x = str(self.dragObject._type1)
        if item is None:
            return
        if 'text' in x:
            self.object = QGraphicsPixmapItem(item.pixmap())
        else:

            self.object = QGraphicsPathItem(item.path())
            gradient = QLinearGradient(1, 1, 1, 5)
            gradient.setColorAt(0, QColor(Qt.gray))
            gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
            gradient.setColorAt(1, QColor(Qt.darkGray))
            self.object.setBrush(QBrush(gradient))
            self.object.setPen(QPen(Qt.NoPen))
            self.object._type1 = item._type1


    def paste(self):
        self.scene.addItem(self.object)
        self.object.setPos(self.scene.grid.x(), self.scene.grid.y())


    def selectedItem(self):
        items = self.scene.selectedItems()

        if len(items) == 1:
            return items[0]
        return None
if __name__=="__main__":
    import sys
    app=QApplication(sys.argv)
    mainWindow = MainWindow()

    mainWindow.show()

    sys.exit(app.exec_())

Tags: selfeventifobjectdefsceneitemqt
1条回答
网友
1楼 · 发布于 2024-09-25 18:24:51

复制QGraphicsItem并不是一项简单的任务,在这种情况下,可以做的是保存最重要的特性,并使用该信息重新创建另一个对象。在这种情况下,可以使用QDataStream来序列化所述信息,这些信息可以很容易地传输到另一个知道如何解码的应用程序。在

import importlib
import random
from PyQt5 import QtCore, QtGui, QtWidgets

custom_mimeType = "application/x-qgraphicsitems"


def item_to_ds(it, ds):
    if not isinstance(it, QtWidgets.QGraphicsItem):
        return
    ds.writeQString(it.__class__.__module__)
    ds.writeQString(it.__class__.__name__)
    ds.writeInt(it.flags())
    ds << it.pos()
    ds.writeFloat(it.opacity())
    ds.writeFloat(it.rotation())
    ds.writeFloat(it.scale())
    if isinstance(it, QtWidgets.QAbstractGraphicsShapeItem):
        ds << it.brush() << it.pen()
    if isinstance(it, QtWidgets.QGraphicsPathItem):
        ds << it.path()


def ds_to_item(ds):
    module_name = ds.readQString()
    class_name = ds.readQString()
    mod = importlib.import_module(module_name)
    it = getattr(mod, class_name)()
    flags = QtWidgets.QGraphicsItem.GraphicsItemFlag(ds.readInt())
    pos = QtCore.QPointF()
    ds >> pos
    it.setFlags(flags)
    it.setPos(pos)
    it.setOpacity(ds.readFloat())
    it.setRotation(ds.readFloat())
    it.setScale(ds.readFloat())

    if isinstance(it, QtWidgets.QAbstractGraphicsShapeItem):
        pen, brush = QtGui.QPen(), QtGui.QBrush()
        ds >> brush
        ds >> pen
        it.setPen(pen)
        it.setBrush(brush)
    if isinstance(it, QtWidgets.QGraphicsPathItem):
        path = QtGui.QPainterPath()
        ds >> path
        it.setPath(path)
    return it


class GraphicsView(QtWidgets.QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag)
        self.setScene(
            QtWidgets.QGraphicsScene(QtCore.QRectF(-200, -200, 400, 400), self)
        )

        for _ in range(4):
            path = QtGui.QPainterPath()
            poly = QtGui.QPolygonF(
                [
                    QtCore.QPointF(0, -40),
                    QtCore.QPointF(-38, -12),
                    QtCore.QPointF(-24, 32),
                    QtCore.QPointF(24, 32),
                    QtCore.QPointF(38, -12),
                    QtCore.QPointF(0, -40),
                ]
            )
            path.addPolygon(poly)
            it = QtWidgets.QGraphicsPathItem(path)
            it.setBrush(QtGui.QColor(*random.sample(range(255), 3)))
            it.setPen(QtGui.QColor(*random.sample(range(255), 3)))
            self.scene().addItem(it)
            it.setPos(QtCore.QPointF(*random.sample(range(-100, 100), 2)))
            it.setFlags(
                it.flags()
                | QtWidgets.QGraphicsItem.ItemIsSelectable
                | QtWidgets.QGraphicsItem.ItemIsMovable
            )

        QtWidgets.QShortcut(
            QtGui.QKeySequence(QtGui.QKeySequence.Copy), self, activated=self.copy_items
        )
        QtWidgets.QShortcut(
            QtGui.QKeySequence(QtGui.QKeySequence.Paste),
            self,
            activated=self.paste_items,
        )

    @QtCore.pyqtSlot()
    def copy_items(self):
        mimedata = QtCore.QMimeData()
        ba = QtCore.QByteArray()
        ds = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
        for it in self.scene().selectedItems():
            item_to_ds(it, ds)
        mimedata.setData(custom_mimeType, ba)
        clipboard = QtGui.QGuiApplication.clipboard()
        clipboard.setMimeData(mimedata)

    @QtCore.pyqtSlot()
    def paste_items(self):
        pos2 = QtCore.QPointF(40, 40)

        clipboard = QtGui.QGuiApplication.clipboard()
        mimedata = clipboard.mimeData()
        if mimedata.hasFormat(custom_mimeType):
            ba = mimedata.data(custom_mimeType)
            ds = QtCore.QDataStream(ba)
            while not ds.atEnd():
                it = ds_to_item(ds)
                self.scene().addItem(it)
                it.setPos(pos2)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = GraphicsView()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())

更新:

^{pr2}$

相关问题 更多 >