似水流年的个人主页

http://www.qtcn.org/bbs/u/127280  [收藏] [复制]

似水流年

  • 24

    关注

  • 11

    粉丝

  • 29

    访客

  • 等级:新手上路
  • 总积分:25
  • 保密,2011-01-01

最后登录:2021-05-11

更多资料

日志

QGraphics解决方案

2013-07-29 16:07

最近一直在做和QGraphics绘图框架相关的项目,在项目中需要通过鼠标控制图元的大小及形状。

鉴于在Qt开发中可能会经常用到,现将源码贴上,以求与众程序猿共勉!

头文件:
sizegripitem.h

  1. #ifndef SIZEGRIPITEM_H
    #define SIZEGRIPITEM_H
    #include <QGraphicsItem>
    #include <QGraphicsRectItem>
    class SizeGripItem : public QGraphicsItem
    {
        private:
            enum
            {
                Top         = 0x1,
                Bottom      = 0x2,
                Left        = 0x4,
                TopLeft     = Top | Left,
                BottomLeft  = Bottom | Left,
                Right       = 0x8,
                TopRight    = Top | Right,
                BottomRight = Bottom | Right
            };
            class HandleItem : public QGraphicsRectItem
            {
                public:
                    HandleItem(int positionFlags, SizeGripItem* parent);
                    int positionFlags() const;
                protected:
                    virtual QVariant itemChange(GraphicsItemChange change,
                                                const QVariant &value);
                private:
                    QPointF restrictPosition(const QPointF& newPos);
                    int positionFlags_;
                    SizeGripItem* parent_;
                                    QPointF                  startPos_ ;
                            protected:
                                    void mousePressEvent(QGraphicsSceneMouseEvent *event);
                                    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
                                    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
            };
        public:
            class Resizer
            {
                public:
                    virtual void operator()(QGraphicsItem* item,
                                            const QRectF& rect) = 0;
            };
            SizeGripItem(Resizer* resizer, QGraphicsItem* parent, QRectF rect);
            virtual ~SizeGripItem();
            virtual QRectF boundingRect() const;
            virtual void paint(QPainter* painter,
                               const QStyleOptionGraphicsItem* option,
                               QWidget* widget = 0);
                    virtual void setScale(qreal scale);
            void setTopLeft(const QPointF& pos);
            void setTop(qreal y);
            void setTopRight(const QPointF& pos);
            void setRight(qreal x);
            void setBottomRight(const QPointF& pos);
            void setBottom(qreal y);
            void setBottomLeft(const QPointF& pos);
            void setLeft(qreal x);
                    void changeRect(const QRectF& rect);
                    void setColor(const QColor& color);
                    void resetColor();
        private:
            void doResize();
            void updateHandleItemPositions();
            QList<HandleItem*> handleItems_;
            QRectF rect_;
            Resizer* resizer_;
    };
    #endif // SIZEGRIPITEM_H


sizegripitem.cpp

  1. #include <QBrush>
    #include <QPen>
    #include "SizeGripItem.h"
    #include <QtWidgets>
    SizeGripItem::HandleItem::HandleItem(int positionFlags, SizeGripItem* parent)
        : QGraphicsRectItem(-3, -3, 6, 6, parent),
          positionFlags_(positionFlags),
          parent_(parent)
    {
        setBrush(QBrush(QColor(173, 224, 255)));
            setPen(QPen(QColor::fromRgb(40, 146, 201), 0));
        setFlags(ItemSendsGeometryChanges | ItemIgnoresTransformations);
            
            switch (positionFlags_) {
            case TopLeft:
            case BottomRight:
                    setCursor( Qt::SizeFDiagCursor ) ;
                    break;
            case Right:
            case Left:
                    setCursor( Qt::SizeHorCursor ) ;
                    break;
            case TopRight:
            case BottomLeft:
                    setCursor(Qt::SizeBDiagCursor);
                    break;
            case Top:
            case Bottom:
                    setCursor(Qt::SizeVerCursor);
                    break;
            default:
                    setCursor(Qt::ArrowCursor);
                    break;
            }
    }
    int SizeGripItem::HandleItem::positionFlags() const
    {
        return positionFlags_;
    }
    void SizeGripItem::HandleItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
    {
            if (event->buttons() & Qt::LeftButton)
            {
                    startPos_ = pos() ;
                    event->accept() ;
            }
            else
            {
                    event->ignore();
            }
    }
    void SizeGripItem::HandleItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
            if (event->buttons() & Qt::LeftButton)
            {
                    QPointF currentParentPos = mapToParent( mapFromScene(event->scenePos()) );;
                    QPointF buttonDownParentPos = mapToParent( mapFromScene(event->buttonDownScenePos(Qt::LeftButton)));
                    setPos( startPos_  + currentParentPos - buttonDownParentPos );
                    event->accept() ;
            }
            else
            {
                    event->ignore();
            }
    }
    void SizeGripItem::HandleItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
    {
            if (event->buttons() & Qt::LeftButton)
            {
                    event->accept() ;
            }
            else
            {
                    event->ignore();
            }
    }
    QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change,
                                                  const QVariant &value)
    {
            QVariant retVal = value;
            if (change == ItemPositionChange)
        {
            retVal = restrictPosition(value.toPointF());
        }
        else if (change == ItemPositionHasChanged)
        {
            QPointF pos = value.toPointF();
            switch (positionFlags_)
            {
                case TopLeft:
                    parent_->setTopLeft(pos);
                    break;
                case Top:
                    parent_->setTop(pos.y());
                    break;
                case TopRight:
                    parent_->setTopRight(pos);
                    break;
                case Right:
                    parent_->setRight(pos.x());
                    break;
                case BottomRight:
                    parent_->setBottomRight(pos);
                    break;
                case Bottom:
                    parent_->setBottom(pos.y());
                    break;
                case BottomLeft:
                    parent_->setBottomLeft(pos);
                    break;
                case Left:
                    parent_->setLeft(pos.x());
                    break;
            }
        }
        return retVal;
    }
    QPointF SizeGripItem::HandleItem::restrictPosition(const QPointF& newPos)
    {
        QPointF retVal = pos();
        if (positionFlags_ & Top || positionFlags_ & Bottom)
            retVal.setY(newPos.y());
        if (positionFlags_ & Left || positionFlags_ & Right)
            retVal.setX(newPos.x());
        if (positionFlags_ & Top && retVal.y() > parent_->rect_.bottom())
            retVal.setY(parent_->rect_.bottom());
        else if (positionFlags_ & Bottom && retVal.y() < parent_->rect_.top())
            retVal.setY(parent_->rect_.top());
        if (positionFlags_ & Left && retVal.x() > parent_->rect_.right())
            retVal.setX(parent_->rect_.right());
        else if (positionFlags_ & Right && retVal.x() < parent_->rect_.left())
            retVal.setX(parent_->rect_.left());
        return retVal;
    }
    SizeGripItem::SizeGripItem(Resizer* resizer, QGraphicsItem* parent, QRectF rect)
        : QGraphicsItem(parent),
          resizer_(resizer)
    {
        rect_ = rect;
        handleItems_.append(new HandleItem(TopLeft, this));
        handleItems_.append(new HandleItem(Top, this));
        handleItems_.append(new HandleItem(TopRight, this));
        handleItems_.append(new HandleItem(Right, this));
        handleItems_.append(new HandleItem(BottomRight, this));
        handleItems_.append(new HandleItem(Bottom, this));
        handleItems_.append(new HandleItem(BottomLeft, this));
        handleItems_.append(new HandleItem(Left, this));
        updateHandleItemPositions();
    }
    SizeGripItem::~SizeGripItem()
    {
        if (resizer_)
            delete resizer_;
    }
    void SizeGripItem::changeRect(const QRectF& rect)
    {
            this->prepareGeometryChange();
            rect_ = rect;
            updateHandleItemPositions();
            this->update();
    }
    QRectF SizeGripItem::boundingRect() const
    {
            QRectF r = rect_;
            //r.adjust(-5, -5, 5, 5);
        return r;
    }
    void SizeGripItem::paint(QPainter* painter,
                             const QStyleOptionGraphicsItem* option,
                             QWidget* widget)
    {
            painter->save();
            QPen pen(QColor(40, 146, 201), 0, Qt::SolidLine);
            pen.setStyle(Qt::DashLine);
            painter->setBrush(Qt::transparent);
            painter->setPen(pen);
            painter->drawRect(rect_);
            painter->restore();
    }
    void SizeGripItem::setScale(qreal scale)
    {
            //QGraphicsItem::setScale(1.0);
    }
    #define IMPL_SET_FN(TYPE, POS)                  
        void SizeGripItem::set ## POS (TYPE v)      
        {                                          
                    prepareGeometryChange();                                
            rect_.set ## POS (v);                  
            doResize();                            
        }
    IMPL_SET_FN(qreal, Top)
    IMPL_SET_FN(qreal, Right)
    IMPL_SET_FN(qreal, Bottom)
    IMPL_SET_FN(qreal, Left)
    IMPL_SET_FN(const QPointF&, TopLeft)
    IMPL_SET_FN(const QPointF&, TopRight)
    IMPL_SET_FN(const QPointF&, BottomRight)
    IMPL_SET_FN(const QPointF&, BottomLeft)
    void SizeGripItem::doResize()
    {
        if (resizer_)
        {
            (*resizer_)(parentItem(), rect_);
                updateHandleItemPositions();
        }
    }
    void SizeGripItem::updateHandleItemPositions()
    {
        foreach (HandleItem* item, handleItems_)
        {
            item->setFlag(ItemSendsGeometryChanges, false);
            switch (item->positionFlags())
            {
                case TopLeft:
                    item->setPos(rect_.topLeft());
                    break;
                case Top:
                    item->setPos(rect_.left() + rect_.width() / 2 - 1,
                                 rect_.top());
                    break;
                case TopRight:
                    item->setPos(rect_.topRight());
                    break;
                case Right:
                    item->setPos(rect_.right(),
                                 rect_.top() + rect_.height() / 2 - 1);
                    break;
                case BottomRight:
                    item->setPos(rect_.bottomRight());
                    break;
                case Bottom:
                    item->setPos(rect_.left() + rect_.width() / 2 - 1,
                                 rect_.bottom());
                    break;
                case BottomLeft:
                    item->setPos(rect_.bottomLeft());
                    break;
                case Left:
                    item->setPos(rect_.left(),
                                 rect_.top() + rect_.height() / 2 - 1);
                    break;
            }
            item->setFlag(ItemSendsGeometryChanges, true);
        }
    }
    void SizeGripItem::setColor(const QColor& color){
              foreach (HandleItem* item, handleItems_){
                      item->setBrush(QBrush(color));
                      item->update();
              }
    }
    void SizeGripItem::resetColor(){
              foreach (HandleItem* item, handleItems_){
                      item->setBrush(QBrush(Qt::green));
                      item->update();
              }
    }




分类:Qt|回复:4|浏览:2570|全站可见|转载
 
 
删除

luhaoting110:只能支持有SetRect的类啊~ 大哥转载的已经删了

2013-10-09 17:31 -

似水流年:对啊,但是你的绘制的图形基础不就是rect吗,不管你要绘制的是什么复杂图形,都是一句rect而来的,所以可以说是都支持啊。

2013-10-10 09:43
删除

luhaoting110:这个类怎么用啊,继承然后实现 Resizer的函数吗?

求完整例子

2013-10-09 14:09 -

似水流年:对啊,实现那个重虚方法,其实就是item的setRect(rect)而已

2013-10-09 15:35

Powered by phpwind v8.7 Certificate Copyright Time now is:04-30 02:09
©2005-2016 QTCN开发网 版权所有 Gzip disabled