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(
  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值