在QGraphicsView中剪切/复制/粘贴

时间:2014-10-25 10:33:02

标签: qt

我想在Qt的QGraphicsView中实现剪切,复制和粘贴操作。我将所有项目存储在一个班级中。我想要的是当我绘制一个项目然后我可以剪切或复制该项目并将其粘贴到我想粘贴的其他位置。任何人都可以建议我采用相同的方法。

cadgraphicsscene.cpp

#include<QtWidgets>
#include "cadgraphicsscene.h"
#include <QGraphicsSceneMouseEvent>
#include <QTextCursor>
#include <QDebug>
CadGraphicsScene::CadGraphicsScene(QObject *parent, QUndoStack *undoStack)
    : QGraphicsScene(parent)
{
    setFlags();
    mUndoStack = undoStack;
    textItem = 0;
    myTextColor = Qt::black;
    // connect selectionChanged signal to selectItems slot
    connect(this, SIGNAL(selectionChanged()), this, SLOT(selectItems()));
}
void CadGraphicsScene::setFlags()
{
    // set/unset all the flags
    mFirstClick = true;
    mSecondClick = false;
    mThirdClick = false;
    mPaintFlag = false;
}
void CadGraphicsScene::setMode(Mode mode)
{
    // determine the mode set
    entityMode = mode;
    if (entityMode == NoMode)
        areItemsSelectable(true);
    else
        areItemsSelectable(false);
}
void CadGraphicsScene::editorLostFocus(mText *item)
{
    QTextCursor cursor = item->textCursor();
    cursor.clearSelection();
    item->setTextCursor(cursor);
    if (item->toPlainText().isEmpty()) {
        removeItem(item);
        item->deleteLater();
    }
}
void CadGraphicsScene::areItemsSelectable(bool b)
{
    // make items selectable
    foreach (QGraphicsItem *item, itemList)
    {
        item->setFlag(QGraphicsItem::ItemIsSelectable, b);
        item->setFlag(QGraphicsItem::ItemIsMovable, b);
    }
}
void CadGraphicsScene::deleteItems()
{
    // delete selected items
    foreach (QGraphicsItem *item, itemList)
    {
        if (item->isSelected())
        {
            mUndoStack->push(new CadCommandDelete(this, item));
            item->setSelected(false);
        }
    }
}
void CadGraphicsScene::selectItems()
{
    // refresh record of selected items and their starting positions
    selectedItems.clear();
    foreach (QGraphicsItem *item, itemList)
    {
        if (item->isSelected())
        {
            if (dynamic_cast<QGraphicsItem *>(item))
            {
                selectedItems.append(qMakePair(
                                         dynamic_cast<QGraphicsItem *>(item),
                                         item->scenePos()));
            }
        }
    }
}
void CadGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    // mousePressEvent in the graphicsScene
    static int id = 0;
    switch (entityMode)
    {
    case NoMode:
        qDebug() << "No Mode";
        break;
    case PointMode:
        pointItem = new Point(++id);
        pointItem->setPos(mouseEvent->scenePos());
        itemList.append(pointItem);
        mUndoStack->push(new CadCommandAdd(this, pointItem));
        break;
    case LineMode:
        if (mFirstClick)
        {
            start_p = mouseEvent->scenePos();
            mFirstClick = false;
            mSecondClick = true;
        }
        else if (!mFirstClick && mSecondClick)
        {
            end_p = mouseEvent->scenePos();
            mPaintFlag = true;
            mSecondClick = false;
        }
        if (mPaintFlag)
        {
            lineItem = new Line(++id, start_p, end_p);
            lineItem->setLine(start_p.x(), start_p.y(), end_p.x(), end_p.y());
            itemList.append(lineItem);
            mUndoStack->push(new CadCommandAdd(this, lineItem));
            setFlags();
        }
        break;
    case CircleMode:
        if (mFirstClick)
        {
            start_p = mouseEvent->scenePos();
            mFirstClick = false;
            mSecondClick = true;
        }
        else if (!mFirstClick && mSecondClick)
        {
            end_p = mouseEvent->scenePos();
            mPaintFlag = true;
            mSecondClick = false;
        }
        if (mPaintFlag)
        {
            circleItem = new Circle(++id, start_p, end_p);
            itemList.append(circleItem);
            mUndoStack->push(new CadCommandAdd(this, circleItem));
            setFlags();
        }
        break;
    case EllipseMode:
        if (mFirstClick)
        {
            start_p = mouseEvent->scenePos();
            mFirstClick = false;
            mSecondClick = true;
        }
        else if (!mFirstClick && mSecondClick)
        {
            mid_p = mouseEvent->scenePos();
            mFirstClick = false;
            mSecondClick = false;
            mThirdClick = true;
        }
        else if (!mSecondClick && mThirdClick)
        {
            end_p = mouseEvent->scenePos();
            mThirdClick = false;
            mPaintFlag = true;
        }
        if (mPaintFlag)
        {
            ellipseItem = new Ellipse(++id, start_p, mid_p, end_p);
            itemList.append(ellipseItem);
            mUndoStack->push(new CadCommandAdd(this, ellipseItem));
            setFlags();
        }
        break;
    case TextMode:
        textItem = new mText(++id);
        textItem->setFont(myFont);
        itemList.append(textItem);
        mUndoStack->push(new CadCommandAdd(this, textItem));
        textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
        textItem->setZValue(1000.0);
        connect(textItem, SIGNAL(lostFocus(mText*)),
                this, SLOT(editorLostFocus(mText*)));
        connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
                this, SIGNAL(itemSelected(QGraphicsItem*)));
        addItem(textItem);
        textItem->setDefaultTextColor(myTextColor);
        textItem->setPos(mouseEvent->scenePos());
        emit textInserted(textItem);
        setFlags();
    default:
        ;
    }
    QGraphicsScene::mousePressEvent(mouseEvent);
}
void CadGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    // if any items moved, then create undo commands
    foreach (itemPos item, selectedItems)
    {
        if (item.first->scenePos() != item.second)
        {
            mUndoStack->push(new CadCommandMove(item.first, item.second.x(),
                                                item.second.y(), item.first->x(),
                                                item.first->y()));
        }
    }
    // refresh record of selected items and call base mouseReleaseEvent
    selectItems();
    QGraphicsScene::mouseReleaseEvent(mouseEvent);
}
void CadGraphicsScene::writeStream(QXmlStreamWriter *stream)
{
    // write entities in a file
    foreach (QGraphicsItem *item, itemList)
    {
        if (items().contains(item))
        {
            if (item->type() == Point::Type)
            {
                Point *myItem = dynamic_cast<Point *>(item);
                stream->writeStartElement("Point");
                stream->writeAttribute("id", QString::number(myItem->id));
                stream->writeAttribute("x", QString::number(myItem->x()));
                stream->writeAttribute("y", QString::number(myItem->y()));
                stream->writeEndElement();  //end of Point Item
            }
            else if (item->type() == Line::Type)
            {
                Line *myItem = dynamic_cast<Line *>(item);
                stream->writeStartElement("Line");
                stream->writeAttribute("id", QString::number(myItem->id));
                stream->writeAttribute("x1", QString::number(myItem->start_p.x()));
                stream->writeAttribute("y1", QString::number(myItem->start_p.y()));
                stream->writeAttribute("x2", QString::number(myItem->end_p.x()));
                stream->writeAttribute("y2", QString::number(myItem->end_p.y()));
                stream->writeEndElement();  //end of Line Item
            }
            else if (item->type() == Circle::Type)
            {
                Circle *myItem = dynamic_cast<Circle *>(item);
                stream->writeStartElement("Circle");
                stream->writeAttribute("id", QString::number(myItem->id));
                stream->writeAttribute("cx", QString::number(myItem->center_p.x()));
                stream->writeAttribute("cy", QString::number(myItem->center_p.y()));
                stream->writeAttribute("radius", QString::number(myItem->radius));
                stream->writeEndElement();  //end of Circle Item
            }
            else if (item->type() == Ellipse::Type)
            {
                Ellipse *myItem = dynamic_cast<Ellipse *>(item);
                stream->writeStartElement("Ellipse");
                stream->writeAttribute("id", QString::number(myItem->id));
                stream->writeAttribute("cx", QString::number(myItem->p1.x()));
                stream->writeAttribute("cy", QString::number(myItem->p1.y()));
                stream->writeAttribute("majR", QString::number(myItem->majRadius));
                stream->writeAttribute("minR", QString::number(myItem->minRadius));
                stream->writeEndElement();  //end of Ellipse Item
            }
            else if (item->type() == mText::Type)
            {
                mText *myItem = dynamic_cast<mText *>(item);
                stream->writeStartElement("MText");
                stream->writeAttribute("id", QString::number(myItem->id));
                stream->writeAttribute("x1", QString::number(myItem->x()));
                stream->writeAttribute("y1", QString::number(myItem->y()));
                stream->writeEndElement();  //end of Text Item
            }
        }
    }
}
void CadGraphicsScene::readStream(QXmlStreamReader *stream)
{
    while (!stream->atEnd())
    {
        stream->readNext();
        if (stream->isStartElement() && stream->name() == "Point")
        {
            qreal x = 0.0, y = 0.0;
            foreach (QXmlStreamAttribute attribute, stream->attributes())
            {
                if (attribute.name() == "xCoord")
                    x = attribute.value().toString().toDouble();
                if (attribute.name() == "yCoord")
                    y = attribute.value().toString().toDouble();
            }
            //            Point *myPoint = new Point;
            //            addItem(myPoint);
            //            myPoint->setPos(x,y);
        }
    }
}

mainwindow.cpp

#include "mainwindow.h"

#include <QGraphicsSceneMouseEvent>
#include <QMouseEvent>
#include <QDebug>
#include <QHBoxLayout>
#include <QDateTime>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextEdit>
#include <QXmlStreamWriter>
#include <QShortcut>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setupUi(this);
    setWindowTitle(tr("eCAD"));
    setCentralWidget(mdiArea);
    Ui_MainWindow::statusBar->showMessage("Welcome to eCAD");

//    connect(pointButton, SIGNAL(clicked()),
//            this, SLOT(drawPoint()));
//    connect(lineButton, SIGNAL(clicked()),
//            this, SLOT(drawLine()));
//    connect(circleButton, SIGNAL(clicked()),
//            this, SLOT(drawCircle()));
//    connect(ellipseButton, SIGNAL(clicked()),
//            this, SLOT(drawEllipse()));

    connect(actionPoints, SIGNAL(triggered()),
            this, SLOT(drawPoint()));
    connect(actionLine, SIGNAL(triggered()),
            this, SLOT(drawLine()));
    connect(actionCircle, SIGNAL(triggered()),
            this, SLOT(drawCircle()));
    connect(actionEllipse, SIGNAL(triggered()),
            this, SLOT(drawEllipse()));
    connect(actionMText, SIGNAL(triggered()),
            this,SLOT(drawText()));

    connect(actionNew, SIGNAL(triggered()),
            this, SLOT(newFile()));
    connect(actionQuit, SIGNAL(triggered()),
            this, SLOT(close()));
    connect(actionPrint, SIGNAL(triggered()),
            this, SLOT(filePrint()));
    connect(actionPrintPreview, SIGNAL(triggered()),
            this, SLOT(filePrintPreview()));
    connect(actionZoom_In, SIGNAL(triggered()),
            this, SLOT(on_actionZoom_In_triggered()));
    connect(actionZoom_Out, SIGNAL(triggered()),
            this, SLOT(on_actionZoom_Out_triggered()));
    connect(actionInsert_Image,SIGNAL(triggered()),
            this, SLOT(on_actionInsert_Image_triggered()));

    // toggle actions to false
    toggleActions(0);
}

MainWindow::~MainWindow()
{
}

void MainWindow::toggleActions(bool b)
{
    actionSave->setEnabled(b);
    actionPrint->setEnabled(b);
    actionPrintPreview->setEnabled(b);
    actionZoom_In->setEnabled(b);
    actionZoom_Out->setEnabled(b);
    actionPoints->setEnabled(b);
    actionLine->setEnabled(b);
    actionCircle->setEnabled(b);
    actionEllipse->setEnabled(b);
    actionMText->setEnabled(b);
    actionInsert_Image->setEnabled(b);
}

void MainWindow::setActions()
{
    // shortcut keys
    new QShortcut(QKeySequence(Qt::Key_Escape),
                  this, SLOT(setNoMode()));
    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_U),
                  this, SLOT(showUndoStack()));
    new QShortcut(QKeySequence(Qt::Key_Delete),
                  this, SLOT(deleteItems()));

    QAction *actionUndo = view->undoStack->createUndoAction(this);
    QAction *actionRedo = view->undoStack->createRedoAction(this);
    actionUndo->setShortcut(QKeySequence::Undo);
    actionRedo->setShortcut(QKeySequence::Redo);
    menuEdit->addAction(actionUndo);
    menuEdit->addAction(actionRedo);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::GraphicsSceneMouseMove)
    {
        QGraphicsSceneMouseEvent *mouseEvent =
                static_cast<QGraphicsSceneMouseEvent *>(event);
        QString showMessage = QString("Mouse move (%1,%2)").
                arg(mouseEvent->scenePos().x()).
                arg(mouseEvent->scenePos().y());
        Ui_MainWindow::statusBar->showMessage(showMessage);
    }
}

void MainWindow::newFile()
{
    // creates a new file
    createMdiView();
    view->newFile();
    view->scene->installEventFilter(this);
    view->show();
    setActions();

    // toggle actions to true
    toggleActions(1);
}

void MainWindow::filePrintPreview()
{
    // display print preview dialog
    QPrinter printer(QPrinter::HighResolution);
    QPrintPreviewDialog preview(&printer, this);
    connect(&preview, SIGNAL(paintRequested(QPrinter *)), SLOT(print(QPrinter *)));
    preview.exec();
}

void MainWindow::filePrint()
{
    // display print dialog and if accepted print
    QPrinter printer(QPrinter::HighResolution);
    QPrintDialog dialog(&printer, this);
    if (dialog.exec() == QDialog::Accepted)
        print(&printer);
}

void MainWindow::print(QPrinter *printer)
{
    // print the page
    QPainter painter(printer);
    int w = printer->pageRect().width();
    int h = printer->pageRect().height();
    QRect page(0, 0, w, h);

    QFont font = painter.font();
    font.setPixelSize((w+h)/100);
    painter.setFont(font);

    painter.drawText(page, Qt::AlignBottom | Qt::AlignRight,
                     QDateTime::currentDateTime().
                     toString(Qt::DefaultLocaleShortDate));

    page.adjust(w/20, h/20, -w/20, -h/20);
    view->scene->render(&painter, page);
}

CadGraphicsView *MainWindow::createMdiView()
{
    // creates a graphicsView and add it to the MDI window
    view = new CadGraphicsView;
    mdiArea->addSubWindow(view);
    return view;
}

void MainWindow::showUndoStack()
{
    // calls an undo stack function of graphicsView
    view->showUndoStack();
}

void MainWindow::drawPoint()
{
    // calls the drawPoint function of graphicsView
    view->drawPoint();
}

void MainWindow::setNoMode()
{
    // calls the setNoMode function of graphicsView
    view->setNoMode();
}

void MainWindow::drawLine()
{
    // calls the drawLine function of graphicsView
    view->drawLine();
}

void MainWindow::drawCircle()
{
    // calls the drawCircle function of graphicsView
    view->drawCircle();
}

void MainWindow::drawEllipse()
{
    // calls the drawEllipse function of graphicsView
    view->drawEllipse();
}

void MainWindow::drawText()
{
    // calls the drawEllipse function of graphicsView
    view->drawText();
}

void MainWindow::deleteItems()
{
    // calls the deleteItems function of graphicsScene
    view->scene->deleteItems();
}

void MainWindow::on_actionOpen_triggered()
{
    // open file dialog box
    QString filename = QFileDialog::getOpenFileName(this,
                                                  tr("Open File"),
                                                  QString(),
                                                  tr("file Name(*.xml)"));
    QMainWindow::statusBar()->showMessage("File opened successfully");
    if (!filename.isEmpty())
    {
        QFile file(filename);
        if (!file.open(QIODevice::ReadOnly))
        {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
        else
        {
            QXmlStreamReader  stream(&file);
            CadGraphicsScene *newScene = new CadGraphicsScene(this,
                                                              view->undoStack);
            while (!stream.atEnd())
            {
                stream.readNext();
                if (stream.isStartElement())
                {
                    if (stream.name() == "SceneData")
                        newScene->readStream(&stream);
                    else
                        stream.raiseError(QString("Unrecognised element '%1'").
                                          arg(stream.name().toString()));
                }
            }

            // check if error occured
            if (stream.hasError())
            {
                file.close();
                QMessageBox::warning(this, "Error",
                                     QString("Failed to load '%1' (%2)").
                                     arg(filename).arg(stream.errorString()));
                delete newScene;
                return;
            }

            /* close file, display new scene, delete old scene
            and display useful message */
            file.close();

            view->setScene( newScene );
            delete view->scene;
            view->scene = newScene;
            QMessageBox::warning(this, "Done",
                                 QString("Loaded '%1'").arg(filename));
            return;
        }
    }
}

void MainWindow::on_actionSave_triggered()
{
    // save file dialog box
    QString filename = QFileDialog::getSaveFileName(this,
                                                  tr("Save File"),
                                                  QString(),
                                                  tr("file Name(*.xml)"));
    if(!filename.isEmpty())
    {
        QFile file(filename);
        if (!file.open(QIODevice::WriteOnly))
        {
            QMessageBox::critical(this, tr("Error"), tr("Could not open file"));
            return;
        }
        else
        {
            QXmlStreamWriter xmlWriter(&file);
            xmlWriter.setAutoFormatting(true);
            xmlWriter.writeStartDocument();
            xmlWriter.writeStartElement("SceneData");
            xmlWriter.writeAttribute("version", "v1.0");
            xmlWriter.writeStartElement("Entities");

            view->scene->writeStream(&xmlWriter);

            xmlWriter.writeEndElement();   //end of Entities
            xmlWriter.writeEndElement();   //end of SceneData
            xmlWriter.writeEndDocument();
            QMessageBox::warning(this, "Saved",
                                 QString("Saved Scene Data to '%1'").
                                 arg(filename));
            file.close();
        }
    }
}

void MainWindow::on_actionZoom_In_triggered()
{
    // Zoom in
    //graphicsView->scale(scaleFactor, scaleFactor);
}

void MainWindow::on_actionZoom_Out_triggered()
{
    // Zoom out
    //graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}

void MainWindow::on_actionInsert_Image_triggered()
{
    // insert image dialog
    QString imagePath = QFileDialog::getOpenFileName(this, tr("open File"),"",
                                                    tr("JPEG(*.jpg *.jpeg);;PNG(*.png)"));
    imageObject = new QImage();
    imageObject->load(imagePath);
    image = QPixmap::fromImage(*imageObject);
    //scene =new CadGraphicsScene(this);
    //scene->addPixmap(image);
    //scene->setSceneRect(image.rect());
    //graphicsView->setScene(scene);
}

使用以下答案我将使上下文菜单正常工作,同时切割操作也可以正常工作。但我的复制和粘贴操作无效。我有不同的类,如点,椭圆等不同的类。我正在添加我的实体类之一,建议我如何进一步继续/

circle.h

#ifndef CIRCLE_H
#define CIRCLE_H

#include <QPainter>
#include <QGraphicsItem>

#include "qmath.h"

class Circle : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    Circle(int, QPointF, QPointF);
    QRectF boundingRect() const;
    virtual void paint(QPainter *painter,
                       const QStyleOptionGraphicsItem *option,
                       QWidget *widget);
    enum { Type = UserType + 3 };
    int type() const;
    int id;

    QPointF center_p, end_p, move_p;
    qreal radius;

private:
    QVector<QPointF> stuff;
};



#endif // CIRCLE_H

circle.cpp

#include "circle.h"

Circle::Circle(int i, QPointF p1, QPointF p2)
{
    // assigns id
    id = i;

    /* set values of center point, end point
    and calculate radius of circle */
    center_p = p1;
    end_p = p2;
    radius = qSqrt(qPow((end_p.x()-center_p.x()), 2)
                   + qPow((end_p.y()-center_p.y()), 2));
}

int Circle::type() const
{
    // Enable the use of qgraphicsitem_cast with circle item.
    return Type;
}

QRectF Circle::boundingRect() const
{
    // bounding rectangle for circle
    return QRectF((center_p.x()-radius), (center_p.y()-radius),
                  (2*radius), (2*radius));
}

void Circle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                   QWidget *widget)
{
    // draws/paints the path of circle
    QPen paintpen(Qt::black);
    paintpen.setWidth(1);
    painter->setRenderHint(QPainter::Antialiasing);

    if (isSelected())
    {
        // sets brush for center point
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::red);
        painter->setPen(paintpen);
        painter->drawEllipse(center_p, 2, 2);

        // sets pen for circumference
        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setBrush(Qt::NoBrush);
        painter->setPen(paintpen);
        painter->drawEllipse(center_p, radius, radius);
    }
    else
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawEllipse(center_p, 2, 2);
        painter->setBrush(Qt::NoBrush);
        painter->drawEllipse(center_p, radius, radius);
    }
}

cadgraphicsscene.cpp

void CadGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* evt)
{
    QList<QGraphicsItem*> itemList = items(evt->scenePos());

    QGraphicsItem* item = itemList.isEmpty() ? 0x00 : itemList.first();

    static QGraphicsItem* storedItem = 0x00;

    QMenu menu;

    //Item found
    if(item)
    {
        menu.addAction("Copy");
        menu.addAction("Cut");
    }

    //An item has been copied/cut
    if(storedItem)
    {
        menu.addAction("Paste");
    }

    QAction* action = menu.exec(evt->screenPos());
    if(action != 0x00)
    {
        if(action->text() == "Copy")
        {
            if(storedItem)
                delete storedItem;
            storedItem = createCopy(item); //has to be implemented
        }
        else if(action->text() == "Cut")
        {
            if(storedItem)
                delete storedItem;
            storedItem = item;
            removeItem(item);
        }
        else if(action->text() == "Paste")
        {
            QGraphicsItem* item = createCopy(storedItem);
            if(item) {
                addItem(item);
                item->setPos(evt->scenePos());
            }
        }
    }
}

QGraphicsItem* CadGraphicsScene::createCopy(QGraphicsItem* item)
{
    if(item == 0x00)
        return 0x00;

    if(item->type() == Circle::Type) //QGraphicsRectItem
    {
        Circle* copy = new Circle(-1, center_p, end_p);


        return copy;
    }

    return 0x00;
}

1 个答案:

答案 0 :(得分:0)

一种可能的方法是将一个插槽连接到视图的customContextMenuRequested信号,请注意必须激活:

view->setContextMenuPolicy(Qt::CustomContextMenu)

在那里你可以获得场景中光标的当前位置。当在该位置有物品时,使用QMenu复制/剪切物品,存储它(或至少存储您需要的信息)......如果没有物品你可以粘贴它(意味着重复使用先前剪切的项目或使用存储的信息创建新项目。

其他方法是创建自定义图形项并覆盖contextMenuEvent或处理mousePressEvent ......

使用您定义的&#34; CadGraphicsScene&#34;的示例覆盖&#34; contextMenuEvent&#34; -Function:

void CadGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* evt)
{
    QList<QGraphicsItem*> itemsAt = items(evt->scenePos());

    QGraphicsItem* item = itemsAt.isEmpty() ? 0x00 : itemsAt.first();

    static QGraphicsItem* storedItem = 0x00;

    QMenu menu;

    //Item found
    if(item)
    {
        menu.addAction("Copy");
        menu.addAction("Cut");
    }

    //An item has been copied/cut
    if(storedItem)
    {
        menu.addAction("Paste");
    }

    QAction* action = menu.exec(evt->screenPos());
    if(action != 0x00)
    {
        if(action->text() == "Copy")
        {
            if(storedItem)
                delete storedItem;
            storedItem = createCopy(item); //has to be implemented
        }
        else if(action->text() == "Cut")
        {
            if(storedItem)
                delete storedItem;
            storedItem = item;
            removeItem(item);
        }
        else if(action->text() == "Paste")
        {
            QGraphicsItem* item = createCopy(storedItem);
            if(item) {
                addItem(item);
                item->setPos(evt->scenePos());
            }
        }
    }
}

QGraphicsItem* CadGraphicsScene::createCopy(QGraphicsItem* item)
{
    if(item == 0x00)
        return 0x00;

    if(item->type() == QGraphicsRectItem::Type) //QGraphicsRectItem
    {           
        QGraphicsRectItem* rectItem = (QGraphicsRectItem*)item;
        QGraphicsRectItem* copy = new QGraphicsRectItem(item->parentItem());
        copy->setRect(rectItem->rect());
        copy->setPen(rectItem->pen());
        copy->setBrush(rectItem->brush());
        return copy;
    }

    return 0x00;
}

本例中的复制函数只处理QGraphicsRectItem,必须扩展所有必需的类型。

测试了使用Qt 4.8 ...

复制圆的例子:

Circle* copy = new Circle(-1, center_p, end_p); //Dont know where you get your ID

然后将&#34; copy&#34; -object添加到场景中。