Search code examples
c++qtqgraphicsview

Cut copy paste in Graphics View


I have 5 entities that can be added in graphics view on mouse events and button clicks. Each entity has been assigned the unique id. I need to add the operations cut, copy and paste on these entities. How to proceed with that. I didn't get any example for cut, copy paste operations in graphics View in Qt. How can I do that?

I have different classes for all entities my class line, circle and ellipse are inherited from QGraphicsItem and line and text from QgraphicsLineItem and QgraphicsEllipse Item. Please tell me how can I work with them too. line.cpp

#include "line.h"

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

    // set values of start point and end point of line
    startP = p1;
    endP = p2;
}

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

QRectF Line::boundingRect() const
{
    qreal extra = 1.0;

    // bounding rectangle for line
    return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                      line().p2().y() - line().p1().y()))
            .normalized()
            .adjusted(-extra, -extra, extra, extra);
}

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

    if (isSelected())
    {
        // sets brush for end points
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::red);
        painter->setPen(paintpen);
        painter->drawEllipse(startP, 2, 2);
        painter->drawEllipse(endP, 2, 2);

        // sets pen for line path
        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawLine(startP, endP);
    }
    else
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawEllipse(startP, 2, 2);
        painter->drawEllipse(endP, 2, 2);
        painter->drawLine(startP, endP);
    }
}

How can I work with this QGraphicsLineItem?


Solution

  • I think you should use custom graphics scene. Create QGraphicsScene subclass. Reimplement keyPressEvent:

    if (e->key() == Qt::Key_C && e->modifiers() & Qt::ControlModifier)
    {
               listCopiedItems =  this->selectedItems();
    }
     
     
    if (e->key() == Qt::Key_V && e->modifiers() & Qt::ControlModifier)
    {
               for(int i=0; i< listCopiedItems.count(); i++)
               {
                  //create new objects, set position and properties 
               }
    }
    

    You can get all needed properties from old objects such as color, size etc and set to new. For cut do same thing but delete old objects from scene and when all work will be done, delete this objects from memory. Also you can create shortcuts with QShortcut class.

    Edit. I want to say that it is very complicate task, so I can't get you code for all cases, for all types. I give just example, but this example works(I tested it). I post here absolutely full code.

    Header:

    #ifndef GRAPHICSSCENE_H
    #define GRAPHICSSCENE_H
    
    #include <QGraphicsScene>
    #include <QStack>
    #include <QPoint>
    #include <QMouseEvent>
    class GraphicsScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        explicit GraphicsScene(QObject *parent = 0);
    
    signals:
    
    protected:
        void mousePressEvent(QGraphicsSceneMouseEvent *event);
        void keyPressEvent(QKeyEvent *event);
    public slots:
        private:
    
        QList<QGraphicsItem *> lst; QPoint last;
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        QVector<QGraphicsEllipseItem * > vec;
    
        };
    
    #endif // GRAPHICSSCENE_H
    

    Cpp:

    #include "graphicsscene.h"
    #include <QDebug>
    #include <QGraphicsSceneMouseEvent>
    #include <QGraphicsItem>
    
    GraphicsScene::GraphicsScene(QObject *parent) :
        QGraphicsScene(parent)
    {
    
    //add something
    addPixmap(QPixmap("G:/2/qt.jpg"));
    
    vec.push_back(addEllipse(0,0,50,50,QPen(Qt::red),QBrush(Qt::blue)));
    vec.push_back(addEllipse(0+100,0+100,50,50,QPen(Qt::red),QBrush(Qt::blue)));
    vec.push_back(addEllipse(0+150,0+150,50,50,QPen(Qt::red),QBrush(Qt::blue)));
    }
    
    void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        //qDebug() << "in";
        if (mouseEvent->button() == Qt::LeftButton)
        {
            last = mouseEvent->scenePos().toPoint();//remember this point, we need it for copying
            QGraphicsItem *item = itemAt(mouseEvent->scenePos(), QTransform());
            item->setFlags(QGraphicsItem::ItemIsSelectable);
            item->setSelected(!item->isSelected());
        }
        QGraphicsScene::mousePressEvent(mouseEvent);
    }
    
    void GraphicsScene::keyPressEvent(QKeyEvent *e)
    {
        if (e->key() == Qt::Key_C && e->modifiers() & Qt::ControlModifier)
        {
            lst = this->selectedItems();
        }
    
        if (e->key() == Qt::Key_V && e->modifiers() & Qt::ControlModifier)
        {
                   for(int i=0; i< lst.count(); i++)
                   {
                      //if it is ellipse
                       QGraphicsEllipseItem *ell = qgraphicsitem_cast<QGraphicsEllipseItem *>(lst.at(i));
                       if(ell)
                       {//then add ellipse to scene with ell properties and new position
                            addEllipse(QRect(last,ell->rect().size().toSize()),ell->pen(),ell->brush());
                               qDebug() << "good";
                       }
    
                   }
        }
    
    
        QGraphicsScene::keyPressEvent(e);
    }
    

    It is so complicate because you have no any clone() method, so you can't clone object with all all properties and move it to the new position. If you have your specific items that you should provide something specific too. That's why it is complex and I can't get code for all cases.

    EDIT

    You can't show scene, you should use this instead:

    QGraphicsView vview;
    GraphicsScene ss;
    vview.setScene(&ss);
    vview.show();