2014-10-25 3 views
-1

Я хочу реализовать операцию вырезания, копирования и вставки в QGraphicsView в 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; 
} 

ответ

0

Одним из возможных способов является подключение слот для у.е. stomContextMenuRequested-сигнал зрения, быть в курсе должен быть активирован:

view->setContextMenuPolicy(Qt::CustomContextMenu) 

там вы можете получить текущую позицию курсора в сцене. Когда в этой позиции есть элемент, используйте QMenu для копирования/вырезания элемента, сохранения его (или, по крайней мере, необходимой вам информации) ... и если нет элемента, который вы можете вставить в него (означает либо повторное использование ранее вырезать элемент или создать новый с сохраненной информацией).

другие способы, например, создание пользовательских графических элемента и перезапись ContextMenuEvent или обработки mousePressEvent ...

Пример использования определенных вами «CadGraphicsScene» перезапись на «ContextMenuEvent» -Функция:

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, должна быть расширена для всех необходимых типов.

Испытано usign Qt 4.8 ...

Пример копирования Круга:

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

, а затем добавить "копировать" -объект на сцену.

+0

Не могли бы вы объяснить мне с помощью небольшого рабочего примера, как использовать QMenu для копирования/вырезания элемента. – user3859872

+0

Пример: я не на своем компьютере, поэтому мне не удалось запустить код, но код мог бы выглядеть выше ... Однако в приведенном выше примере есть много возможных улучшений, например, например, создание QMenu внутри класса и повторно использовать его каждый раз (обновлять видимость действий каждый раз при вызове contextmenu) ... – Robert

+0

Вы попробовали мой пример? @ user3859872 – Robert