天天看点

QGraphicsView 框架学习(一)、图形元素的编辑

QGraphicsView 框架学习(一)、图形元素的编辑

代码在 http://download.csdn.net/detail/firebolt2002/8782273

一、给图形对象加控制点,用户通过鼠标来操作控制点来编辑图形,参考MFC drawcli的实现。

很多人通过QGraphicsItem的派生类,然后重载几个函数来处理鼠标消息:

void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvet) Q_DECL_OVERRIDE;
           

这种在图元对象内部处理鼠标消息的方法我使用过,感觉不太好用,主要是鼠标消息有时候收不到,操作比方麻烦。所以我现在通过派生一个QGraphicsScene对象,重载它的鼠标处理函数来操作图元对象,这样感觉更合理一些。

先来看看控制点对象,我从QtCreator里抄的:

下面看看图元对象。

//控制手柄的大小
enum { SELECTION_HANDLE_SIZE = 6, SELECTION_MARGIN = 10 };
enum SelectionHandleState { SelectionHandleOff, SelectionHandleInactive, SelectionHandleActive };
 
 
//通过QGraphicsRectItem派生,它本来就是个矩形嘛。
class SizeHandleRect :public QGraphicsRectItem
{    //控制点的操作方向。
    enum Direction { None = -1 , LeftTop , Top, RightTop, Right, RightBottom, Bottom, LeftBottom, Left , Extra };
    SizeHandleRect(QGraphicsItem* parent , Direction d, QGraphicsItem *resizable);
    Direction dir() const  { return m_dir; }
    void updateCursor();
    void setState(SelectionHandleState st);
    bool hitTest( const QPointF & point );
    void move(qreal x, qreal y );
 
protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
 
private:
    const Direction m_dir;
    QGraphicsItem *m_resizable;
    SelectionHandleState m_state;
    QColor borderColor;
};
 
           
<pre name="code" class="cpp">//手柄的绘制部分,挺简单,就是画个6x6的小矩形。 
void SizeHandleRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //不知道为啥,打开反走样后,如果加框,会很难看。
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(borderColor));
 
    if ( m_dir >= Extend )
    {
     //   painter->setBrush(QBrush("lightseagreen"));
     //如果是额外的控制点,就画圈。
        painter->drawEllipse(rect());
    }else
        painter->drawRect(rect());
 
}
 
//父对象状态改变,根据状态决定是否可见。
void SizeHandleRect::setState(SelectionHandleState st)
{
    if (st == m_state)
        return;
    switch (st) {
    case SelectionHandleOff:
        hide();
        break;
    case SelectionHandleInactive:
    case SelectionHandleActive:
        show();
        break;
    }
    m_state = st;
}
//检查是否选中。
bool SizeHandleRect::hitTest(const QPointF &point)
{
    QPointF pt = mapFromScene(point);
    bool result = rect().contains(pt);
    return result;
}
//移动到指定的位置。
void SizeHandleRect::move(qreal x, qreal y)
{
    setPos(x,y);
}
 
 
//使用QGraphicsObject做父类,主要是想利用一下它的元属性,这样可以做一个通用的属性编辑器,后来发现很鸡肋,QPen,QBrush居然不支持,还得自己写,用它就
不划算了。
class GraphicsBasicItem : public QGraphicsObject
{
    Q_OBJECT
    Q_PROPERTY(QColor pen READ penColor WRITE setPen )
    Q_PROPERTY(QColor brush READ brush WRITE setBrush )
public:
    explicit GraphicsBasicItem(QGraphicsItem * parent);
    explicit GraphicsBasicItem(const QString &name ,QGraphicsItem *parent );
    virtual ~GraphicsBasicItem();
    QColor brush() const {return m_brush.color();}
    QPen   pen() const {return m_pen;}
    QColor penColor() const {return m_pen.color();}
    void   setPen(const QPen & pen ) { m_pen = pen;}
    void   setBrush( const QBrush & brush ) { m_brush = brush ; }
protected:
    QBrush m_brush;
    QPen   m_pen ;
};
 
//这个才图元对象。
class GraphicsItem : public GraphicsBasicItem
{
    Q_OBJECT
public:
    GraphicsItem(QGraphicsItem * parent );
    enum {Type = UserType+1};
    int  type() const { return Type; }
    //返回选中的控制点
    virtual SizeHandleRect::Direction  hitTest( const QPointF & point ) const;
    //根据控制点当前的位置改变对象的大小。
    virtual void resizeTo(SizeHandleRect::Direction dir, const QPointF & point );
    //返回控制点的光标<span style="white-space:pre">	</span>
    virtual Qt::CursorShape getCursor(SizeHandleRect::Direction dir );
    //返回本地坐标
    virtual QRectF  rect() const { return m_localRect;}
    //当释放鼠标完成size操作后,重建本地坐标。 
    virtual void changeSize () {}</span>
    virtual void move( const QPointF & point ){}
    int  getHandleCount() const { return m_handles.count();}
signals:
    void selectedChange(QGraphicsItem *item);
protected:
    virtual void updateGeometry();
    void setState(SelectionHandleState st);
    void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
    typedef QVector<SizeHandleRect*> Handles;
    Handles m_handles;
    QRectF m_localRect;
};
           

创建手柄的过程,和改变手柄状态的方法。

创建手柄的过程可以在每个具体对象中实现,比如矩形有8个控制点,线有2个控制点,多边形控制点就是实际的点数。

GraphicsRectItem::GraphicsRectItem(const QRect & rect ,QGraphicsItem *parent)
    :GraphicsItem(parent)
    ,m_width(rect.width())
    ,m_height(rect.height())
{
 
    // handles
    m_handles.reserve(SizeHandleRect::None);
    for (int i = SizeHandleRect::LeftTop; i <= SizeHandleRect::Left; ++i) {
        SizeHandleRect *shr = new SizeHandleRect(this, static_cast<SizeHandleRect::Direction>(i), this);
        m_handles.push_back(shr);
    }
    updateGeometry();
    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemIsSelectable, true);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
    //至少需要一个图元对象打开次方法,否则QGraphicsScene不返还鼠标事件.
    this->setAcceptHoverEvents(true);
}
//移动手柄位置。
void GraphicsItem::updateGeometry()
{
    const QRectF &geom = this->boundingRect();
 
    const int w = SELECTION_HANDLE_SIZE;
    const int h = SELECTION_HANDLE_SIZE;
 
    const Handles::iterator hend =  m_handles.end();
    for (Handles::iterator it = m_handles.begin(); it != hend; ++it) {
        SizeHandleRect *hndl = *it;;
        switch (hndl->dir()) {
        case SizeHandleRect::LeftTop:
            hndl->move(geom.x() - w / 2, geom.y() - h / 2);
            break;
        case SizeHandleRect::Top:
            hndl->move(geom.x() + geom.width() / 2 - w / 2, geom.y() - h / 2);
            break;
        case SizeHandleRect::RightTop:
            hndl->move(geom.x() + geom.width() - w / 2, geom.y() - h / 2);
            break;
        case SizeHandleRect::Right:
            hndl->move(geom.x() + geom.width() - w / 2, geom.y() + geom.height() / 2 - h / 2);
            break;
        case SizeHandleRect::RightBottom:
            hndl->move(geom.x() + geom.width() - w / 2, geom.y() + geom.height() - h / 2);
            break;
        case SizeHandleRect::Bottom:
            hndl->move(geom.x() + geom.width() / 2 - w / 2, geom.y() + geom.height() - h / 2);
            break;
        case SizeHandleRect::LeftBottom:
            hndl->move(geom.x() - w / 2, geom.y() + geom.height() - h / 2);
            break;
        case SizeHandleRect::Left:
            hndl->move(geom.x() - w / 2, geom.y() + geom.height() / 2 - h / 2);
            break;
        default:
            break;
        }
    }
}
           
这个类里有两个方法比较重要,一个就是resizeTo,另外一个就是changeSize(),resizeTo就是改变对象的大小,为啥还要有个changeSize方法呢。这个问题后面说。
先看看这两个函数的具体实现。
void GraphicsRectItem::resizeTo(SizeHandleRect::Direction dir, const QPointF &point)
{
    // 将场景坐标映射为本地坐标。
    QPointF local = mapFromParent(point);
    QString dirName;
    // 临时对象,记录改变后的大小。
    QRect delta = this->rect().toRect();
    switch (dir) {
    case SizeHandleRect::Right:
        dirName = "Rigth";
        delta.setRight(local.x());
        break;
    case SizeHandleRect::RightTop:
        dirName = "RightTop";
        delta.setTopRight(local.toPoint());
        break;
    case SizeHandleRect::RightBottom:
        dirName = "RightBottom";
        delta.setBottomRight(local.toPoint());
        break;
    case SizeHandleRect::LeftBottom:
        dirName = "LeftBottom";
        delta.setBottomLeft(local.toPoint());
        break;
    case SizeHandleRect::Bottom:
        dirName = "Bottom";
        delta.setBottom(local.y());
        break;
    case SizeHandleRect::LeftTop:
        dirName = "LeftTop";
        delta.setTopLeft(local.toPoint());
        break;
    case SizeHandleRect::Left:
        dirName = "Left";
        delta.setLeft(local.x());
        break;
    case SizeHandleRect::Top:
        dirName = "Top";
        delta.setTop(local.y());
        break;
   default:
        break;
    }
    // 改变矩形的大小。
   prepareGeometryChange();
 
    m_width = delta.width();    m_height = delta.height();
    //改变本地坐标系,这里本地坐标系已经被破坏了,如果进行旋转操作等其他变换后,坐标系会出问题。
    //还需要调用changeSize来重建本地坐标。
    m_localRect = delta;
    updateGeometry();
}
           
重建本地坐标。
   为啥要重建本地坐标系呢,前面已经说了,如果改变图元的尺寸,本地坐标系就会跟着改变。本地坐标又是啥样子呢,它是用户自己的坐标系,不管视图坐标,还是场景坐标他们的改变不会影响到本地坐标,通常情况下,我们会将本地坐标定义为原点在中心位置的坐标系,这个坐标比较好操作,也可以定义为原点在左上角位置。如果加入旋转等变换,最好还是把原点放到中心位置。
   当我们改变对象的大小后,本地坐标原点发生了改变,我们要调整一下坐标,使它的原点重新回到中心位置。
void GraphicsRectItem::changeSize()
{
    QPointF pt1,pt2,delta;
    //获得当前原点的场景坐标
    pt1 = mapToScene(transformOriginPoint());
    //获得改变后坐标系的中心位置,的场景坐标。
    pt2 = mapToScene(boundingRect().center());
    //计算位移
    delta = pt1 - pt2;
 
    prepareGeometryChange();
    
    //重建本地坐标系,使原点处于中心位置。
    m_localRect = QRectF(-m_width/2,-m_height/2,m_width,m_height);
    //移动图元对象的坐标原点。
    setTransform(transform().translate(delta.x(),delta.y()));
    //将当前图形原点移动到新的坐标系中心位置。
    setTransformOriginPoint(boundingRect().center());
    //将图形的pos移动到原点上。
    moveBy(-delta.x(),-delta.y());<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
   //还原图形坐标原点 
    setTransform(transform().translate(-delta.x(),-delta.y()));
    qDebug()<<"changeOrigin: "<< delta << mapFromScene( pos()) << mapFromScene(pt2)<<m_localRect;
 
    updateGeometry();
 
}
           
这里多边形重新本地坐标过程有些不一样,需要对每个点的坐标进行重建。
void GraphicsPolygonItem::changeSize()
{
 
    QPointF pt1,pt2,delta;
    //把原来的点映射到场景坐标
    QPolygonF pts = mapToScene(m_points);
    pt1 = mapToScene(transformOriginPoint());
    pt2 = mapToScene(boundingRect().center());
    delta = pt1 - pt2;
    //对每个点进行移动,重建坐标系
    for (int i = 0; i < pts.count() ; ++i )
        pts[i]+=delta;
 
    //还原本地坐标
    m_points = mapFromScene(pts);
 
    setTransform(transform().translate(delta.x(),delta.y()));
    setTransformOriginPoint(boundingRect().center());
    moveBy(-delta.x(),-delta.y());
    setTransform(transform().translate(-delta.x(),-delta.y()));
    prepareGeometryChange();
 
    qDebug()<<"changeOrigin: "<< delta << mapFromScene( pos()) << transformOriginPoint()<<boundingRect();
 
    updateGeometry();
 
}
//场景类,这里传递鼠标消息给绘图工具。
class DrawScene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit DrawScene(QObject *parent = 0);
    void setView(QGraphicsView * view ) { m_view = view ; }<pre name="code" class="cpp">class DrawTool
{
public:
    DrawTool( DrawShape shape );
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene );
    virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event ,DrawScene *scene );
    DrawShape m_drawShape;
    bool m_hoverSizer;
 
    static DrawTool * findTool( DrawShape drawShape );
    static QList<DrawTool*> c_tools;
    static QPointF c_down;
    static quint32 c_nDownFlags;
    static QPointF c_last;
    static DrawShape c_drawShape;
};
 
//绘图工具类,参考drawcli
class SelectTool : public DrawTool
{
public:
    SelectTool();
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene );
    QSizeF  m_lastSize;
    QPointF initialPositions;
    QGraphicsPathItem * dashRect;
};
 
class  RotationTool : public DrawTool
{
public:
    RotationTool();
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene );
    qreal lastAngle;
    QGraphicsPathItem * dashRect;
};
 
class RectTool : public DrawTool
{
public:
    RectTool(DrawShape drawShape);
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene );
    GraphicsItem * item;
};
 
class PolygonTool : public DrawTool
{
public:
    PolygonTool(DrawShape shape );
    virtual void mousePressEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene ) ;
    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event , DrawScene * scene );
    virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * event ,DrawScene *scene );
    GraphicsPolygonItem * item;
    QPointF initialPositions;
 
};
           
<pre name="code" class="cpp"><pre name="code" class="cpp">class DrawScene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit DrawScene(QObject *parent = 0);
    void setView(QGraphicsView * view ) { m_view = view ; }
    QGraphicsView * view() { return m_view; };
    void mouseEvent(QGraphicsSceneMouseEvent *mouseEvent );
 
signals:
    void itemSelected(QGraphicsItem *item);
 
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) Q_DECL_OVERRIDE;
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvet) Q_DECL_OVERRIDE;
    QGraphicsView * m_view;
 
};
           
//场景类的具体实现
<pre name="code" class="cpp">DrawScene::DrawScene(QObject *parent)
    :QGraphicsScene(parent)
{
    m_view = NULL;
 
}
//有些消息需要继续传递给QGraphicsScene,可以通过这个函数传回来。
void DrawScene::mouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    switch( mouseEvent->type() ){
    case QEvent::GraphicsSceneMousePress:
        QGraphicsScene::mousePressEvent(mouseEvent);
        break;
    case QEvent::GraphicsSceneMouseMove:
        QGraphicsScene::mouseMoveEvent(mouseEvent);
        break;
    case QEvent::GraphicsSceneMouseRelease:
        QGraphicsScene::mouseReleaseEvent(mouseEvent);
        break;
    }
}
 
 
void DrawScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
 
    DrawTool * tool = DrawTool::findTool( DrawTool::c_drawShape );
    if ( tool )
        tool->mousePressEvent(mouseEvent,this);
}
 
void DrawScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    DrawTool * tool = DrawTool::findTool( DrawTool::c_drawShape );
    if ( tool )
        tool->mouseMoveEvent(mouseEvent,this);
}
 
void DrawScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    DrawTool * tool = DrawTool::findTool( DrawTool::c_drawShape );
    if ( tool )
        tool->mouseReleaseEvent(mouseEvent,this);
}
 
void DrawScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvet)
{
    DrawTool * tool = DrawTool::findTool( DrawTool::c_drawShape );
    if ( tool )
        tool->mouseDoubleClickEvent(mouseEvet,this);
 
}
           
//选择工具的具体实现
<pre name="code" class="cpp">SelectTool::SelectTool()
    :DrawTool(selection)
{
    m_lastSize.setHeight(0);
    m_lastSize.setWidth(0);
    dashRect = 0;
}
 
void SelectTool::mousePressEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
    DrawTool::mousePressEvent(event,scene);
 
    QPointF itemPoint;
 
    if (!m_hoverSizer)
      scene->mouseEvent(event);
 
    selectMode = none;
    QList<QGraphicsItem *> items = scene->selectedItems();
    GraphicsItem *item = 0;
 
    if ( items.count() == 1 )
        item = qgraphicsitem_cast<GraphicsItem*>(items.first());
 
    if ( item != 0 ){
 
        nDragHandle = item->hitTest(event->scenePos());
        if ( nDragHandle !=SizeHandleRect::None)
             selectMode = size;
        else
            selectMode =  move;
 
        m_lastSize = item->boundingRect().size();
        itemPoint = item->mapFromScene(c_down);
 
        setCursor(scene,Qt::ClosedHandCursor);
 
    }
 
 
    if( selectMode == none ){
        selectMode = netSelect;
        if ( scene->view() ){
            QGraphicsView * view = scene->view();
            view->setDragMode(QGraphicsView::RubberBandDrag);
        }
 
    }
 
 
    if ( selectMode == move && items.count() == 1 ){
 
        if (dashRect ){
            scene->removeItem(dashRect);
            delete dashRect;
            dashRect = 0;
        }
 
        dashRect = new QGraphicsPathItem(item->shape());
        dashRect->setPen(Qt::DashLine);
        dashRect->setPos(item->pos());
        dashRect->setTransformOriginPoint(item->transformOriginPoint());
        dashRect->setTransform(item->transform());
        dashRect->setRotation(item->rotation());
        dashRect->setScale(item->scale());
        initialPositions = dashRect->pos();
        scene->addItem(dashRect);
    }
}
 
void SelectTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
 
    DrawTool::mouseMoveEvent(event,scene);
    QList<QGraphicsItem *> items = scene->selectedItems();
    GraphicsItem * item = 0;
    if ( items.count() == 1 ){
        item = qgraphicsitem_cast<GraphicsItem*>(items.first());
        if ( item != 0 ){
            if ( nDragHandle != SizeHandleRect::None && selectMode == size ){
                QSizeF delta(c_last.x() - c_down.x() , c_last.y() - c_down.y());
                item->resizeTo(nDragHandle,c_last);
            }
            else if(nDragHandle == SizeHandleRect::None && selectMode == selection ){
                 SizeHandleRect::Direction handle = item->hitTest(event->scenePos());
                 if ( handle != SizeHandleRect::None){
                     setCursor(scene,Qt::OpenHandCursor/*item->getCursor(handle)*/);
                     m_hoverSizer = true;
                 }else{
                     setCursor(scene,Qt::ArrowCursor);
                     m_hoverSizer = false;
                 }
             }
        }
    }
    if ( selectMode == move ){
        if ( dashRect ){
            dashRect->setPos(initialPositions + c_last - c_down);
        }
    }
    if ( selectMode != size  && items.count() > 1)
    {
        scene->mouseEvent(event);
 
    }
 
}
 
void SelectTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
    DrawTool::mouseReleaseEvent(event,scene);
 
    QList<QGraphicsItem *> items = scene->selectedItems();
    if ( items.count() == 1 ){
        GraphicsItem * item = qgraphicsitem_cast<GraphicsItem*>(items.first());
        if ( item != 0  && selectMode == move && c_last != c_down ){
             item->setPos(initialPositions + c_last - c_down);
             qDebug()<<"move to :" << item->mapFromScene(item->pos());
        }else if ( item !=0 && selectMode == size && c_last != c_down ){
            item->changeSize();
        }
    }
 
    if (selectMode == netSelect ){
 
        if ( scene->view() ){
            QGraphicsView * view = scene->view();
            view->setDragMode(QGraphicsView::NoDrag);
        }
    }
 
    if (dashRect ){
        scene->removeItem(dashRect);
        delete dashRect;
        dashRect = 0;
    }
 
    selectMode = none;
    nDragHandle = SizeHandleRect::None;
    m_hoverSizer = false;
    scene->mouseEvent(event);
 
}
           
创建矩形工具
RectTool::RectTool(DrawShape drawShape)
    :DrawTool(drawShape)
{
    item = 0;
}
 
void RectTool::mousePressEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
    DrawTool::mousePressEvent(event,scene);
 
    scene->clearSelection();
    switch ( c_drawShape ){
    case rectangle:
        item = new GraphicsRectItem(QRect(0,0,0,0),NULL);
        break;
    case roundrect:
        item = new GraphicsRoundRectItem(QRect(0,0,0,0),NULL);
        break;
    case ellipse:
        item = new GraphicsEllipseItem(QRect(0,0,0,0),NULL);
        break;
    case line:
        item = new GraphicsLineItem(0);
        break;
    case arc:
        item = new GraphicsArcItem(0);
        break;
    }
    if ( item == 0) return;
    item->setPos(event->scenePos());
    scene->addItem(item);
 
    scene->connect(item, SIGNAL(selectedChange(QGraphicsItem*)),
            scene, SIGNAL(itemSelected(QGraphicsItem*)));
 
    item->setSelected(true);
    //设置当前状态为改变大小
    selectMode = size;
        //设置当前控制点为右下角。
    nDragHandle = SizeHandleRect::RightBottom;
 
}
 
void RectTool::mouseMoveEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
    setCursor(scene,Qt::CrossCursor);
    //传递消息给选择工具
    selectTool.mouseMoveEvent(event,scene);
}
 
void RectTool::mouseReleaseEvent(QGraphicsSceneMouseEvent *event, DrawScene *scene)
{
    if ( event->scenePos() == c_down ){
 
       if ( item != 0){
         item->setSelected(false);
         scene->removeItem(item);
         delete item ;
         item = 0;
       }
       selectTool.mousePressEvent(event,scene);
       qDebug()<<"RectTool removeItem:";
    }
    selectTool.mouseReleaseEvent(event,scene);
    c_drawShape = selection;
}
           

后面还有旋转工具,多边形工具等,就不一一贴代码了。

继续阅读