图形视图中的剪贴板操作

时间:2014-11-01 17:56:34

标签: c++ qt

我的实体有不同的子类。实体在GraphicsView中绘制,如何将剪贴板操作应用于剪切,复制和粘贴。

gEntity.h

#ifndef GENTITY_H
#define GENTITY_H
class gEntity :public QObject
{

public:
    gEntity(QObject* parent=0) : QObject(parent) {}
    virtual ~gEntity() {}

    virtual gEntity* my_clone() { return 0; }
};

#endif // GENTITY_H

circle.h

    #ifndef CIRCLE_H
    #define CIRCLE_H

    #include <QPainter>
    #include <QGraphicsItem>
    #include <gentity.h>

    #include "qmath.h"


    class Circle : public QObject, public QGraphicsItem, public gEntity
    {
        Q_OBJECT

    public:
        Circle(QObject* parent=0) : gEntity(parent){

        }

        Circle(int, QPointF, QPointF);
        Circle(int, QPointF, qreal);
        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;
        void setRadius((const qreal &radius);

      private:
        QVector<QPointF> stuff;
    };

#endif // CIRCLE_H

circle.cpp

#include "circle.h"
#include "gentity.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));
}

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

    /* set values of center point
       and radius of circle */
    center_p = p1;
    radius = rad;
}

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->save();
        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);
        painter->restore();
    }
}
 gEntity* my_clone(){
   Circle *c = new Circle();
   c->setRadius(radius);
   return c;

 }

Clipboard.h

#include<QStack>
#include<QClipboard>
class MyClipBoard
{
public:
    static MyClipBoard* instance()
    {
        if(!inst)
            inst = new MyClipBoard;
        return inst;
    }

    void push(gEntity* g) {
        clips.push(g);
    }

    gEntity* last()
    {
        if(clips.count() == 0) return 0;
        return clips.last();
    }

    gEntity* pop()
    {
        if(clips.count() == 0) return 0;
        return clips.pop();
    }

    bool isempty() const { return clips.empty(); }

private:
    QStack<gEntity*> clips;
    static MyClipBoard* inst;
};

CadgraphicsScene.cpp

   MyClipBoard* MyClipBoard::inst = 0;



    CadGraphicsScene::CadGraphicsScene(QObject *parent, QUndoStack *undoStack)
        : QGraphicsScene(parent)
    {
        setFlags();
        id = 0;
        mUndoStack = undoStack;
        m_context = new QMenu;
        m_context->addAction("Insert Circle");
        a_cut = m_context->addAction("cut");
        a_copy = m_context->addAction("copy");
        a_paste = m_context->addAction("paste");
        context_item = 0;
        connect(m_context, SIGNAL(triggered(QAction*)), this, SLOT(contmenu(QAction*)));

    }
    void CadGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
        m_context->exec(event->screenPos());
    }
    void CadGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        // mousePressEvent in the graphicsScene
        if(mouseEvent->button() == Qt::LeftButton)
        {
            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->setPos(mouseEvent->scenePos());
                itemList.append(textItem);
                textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
                mUndoStack->push(new CadCommandAdd(this, textItem));
                connect(textItem, SIGNAL(lostFocus(mText*)),
                        this, SLOT(editorLostFocus(mText*)));
                connect(textItem, SIGNAL(selectedChange(QGraphicsItem*)),
                        this, SIGNAL(itemSelected(QGraphicsItem*)));
                setFlags();

            default:
                ;
            }
        }else if(event->button() & Qt::RightButton)
            {
                context_item = itemAt(event->scenePos().toPoint(), QTransform());//base operand not a pointer
                cpos = event->scenePos();//says invalid use of member function

                if(!context_item)//Here it says all variables out of scope
                {
                    a_cut->setEnabled(false);
                    a_copy->setEnabled(false);
                    if(MyClipBoard::instance()->isempty())
                        a_paste->setEnabled(false);
                    else a_paste->setEnabled(true);
                }
                else
                {
                    a_cut->setEnabled(true);
                    a_copy->setEnabled(true);
                    a_paste->setEnabled(false);
                }
            }



        QGraphicsScene::mousePressEvent(mouseEvent);
    }

cadgraphicsscene.h

private:
 QMenu* m_context;
    QAction* a_cut;
    QAction* a_copy;
    QAction* a_paste;
    QGraphicsItem* context_item;
    QPointF cpos;

1 个答案:

答案 0 :(得分:2)

你是什​​么意思切割grahicsitem? (改变其位置或转移到另一个视图)

用于复制和粘贴搜索在c ++中克隆对象并不难,而在粘贴时只需更改新对象的位置并将其添加到图形视图或场景

更新

#ifndef MYSCENE_H
#define MYSCENE_H

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>

#include <QGraphicsSceneContextMenuEvent>

#include <QMenu>
#include <QStack>

class gEntity : public QObject, public QGraphicsItem
{
public:
    gEntity(QObject* parent=0) : QObject(parent) {}
    virtual ~gEntity() {}

    virtual gEntity* my_clone() { return 0; }
};

class Circle : public gEntity
{
public:
    Circle(QObject* parent=0) : gEntity(parent) {
        m_radius = 10;
    }

    qreal radius() const;
    void setRadius(const qreal &radius);

    gEntity* my_clone()
    {
        Circle* c = new Circle;
        c->setRadius(m_radius);
        return c;
    }

    QRectF boundingRect() const
    {
        return QRectF(-m_radius, -m_radius, 2 * m_radius, 2 * m_radius);
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        painter->save();
        painter->setBrush(Qt::yellow);
        painter->drawEllipse(QPointF(0,0), m_radius, m_radius);
        painter->restore();
    }

private:
    qreal m_radius;
};


class MyClipBoard
{
public:
    static MyClipBoard* instance()
    {
        if(!inst)
            inst = new MyClipBoard;
        return inst;
    }

    void push(gEntity* g) {
        clips.push(g);
    }

    gEntity* last()
    {
        if(clips.count() == 0) return 0;
        return clips.last();
    }

    gEntity* pop()
    {
        if(clips.count() == 0) return 0;
        return clips.pop();
    }

    bool isempty() const { return clips.empty(); }

private:
    QStack<gEntity*> clips;
    static MyClipBoard* inst;
};

class MyScene : public QGraphicsScene
{
    Q_OBJECT
public:
    MyScene(QObject* parent=0);

    virtual ~MyScene()
    {
        delete m_context;
    }

protected:
    void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
    void mousePressEvent(QGraphicsSceneMouseEvent* event);

public slots:
    void insertCircle(const QPointF& pos)
    {
        Circle* mcircle = new Circle;
        addItem(mcircle);
        mcircle->setPos(pos);
    }

    void cut(gEntity* obj)
    {
        removeItem(obj);
        MyClipBoard::instance()->push(obj);
    }

    void copy(gEntity* obj)
    {
        MyClipBoard::instance()->push(obj->my_clone());
    }

    void paste(const QPointF& pos)
    {
        gEntity* last = MyClipBoard::instance()->pop();
        if(last)
        {
            addItem(last);
            last->setPos(pos);
        }
    }

    void contmenu(QAction* a)
    {
        if(a->text() == "Insert Circle")
        {
            insertCircle(cpos);
        }
        else if(a == a_cut)
        {
            cut(static_cast<gEntity*>(context_item));
        }
        else if(a == a_copy)
        {
            copy(static_cast<gEntity*>(context_item));
        }
        else if(a == a_paste)
        {
            paste(cpos);
        }
    }

private:
    QMenu* m_context;
    QAction* a_cut;
    QAction* a_copy;
    QAction* a_paste;
    QGraphicsItem* context_item;
    QPointF cpos;
};

#endif // MYSCENE_H

scene.cpp

#include "myscene.h"
#include <QGraphicsSceneMouseEvent>

MyClipBoard* MyClipBoard::inst = 0;

qreal Circle::radius() const
{
    return m_radius;
}

void Circle::setRadius(const qreal &radius)
{
    m_radius = radius;
}

MyScene::MyScene(QObject *parent) : QGraphicsScene(parent)
{
    m_context = new QMenu;
    m_context->addAction("Insert Circle");
    a_cut = m_context->addAction("cut");
    a_copy = m_context->addAction("copy");
    a_paste = m_context->addAction("paste");
    context_item = 0;

    connect(m_context, SIGNAL(triggered(QAction*)), this, SLOT(contmenu(QAction*)));
}

void MyScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){
    m_context->exec(event->screenPos());
}

void MyScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsScene::mousePressEvent(event);

    if(event->button() & Qt::RightButton)
    {
        context_item = itemAt(event->scenePos().toPoint(), QTransform());
        cpos = event->scenePos();

        if(!context_item)
        {
            a_cut->setEnabled(false);
            a_copy->setEnabled(false);
            if(MyClipBoard::instance()->isempty())
                a_paste->setEnabled(false);
            else a_paste->setEnabled(true);
        }
        else
        {
            a_cut->setEnabled(true);
            a_copy->setEnabled(true);
            a_paste->setEnabled(false);
        }
    }
}

的main.cpp

#include <QApplication>

#include "myscene.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsView w(new MyScene);
    w.setSceneRect(0,0,500,500);
    w.show();

    return a.exec();
}