Qt之QGraphicsView实战篇
作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,⾮商业转载请注明出处
前⾔
前⾯的章节介绍了 Graphics View 绘图架构,终于到实战了,真的是千呼万唤始出来!这⼀章节就⽤ Graphics View 绘图架构来做⼀个绘图⼯具,实现⼀些基础图形的绘制,废话不多说先来看⼀下结果演⽰:
图形绘制介绍
我们知道简单的⼏何图形,只要确定两个点就可以完成绘制。⽐如要画⼀个圆,⼀个点可以定为圆⼼,由另⼀个点则可以计算出到圆⼼的距离,即圆的为半径,确定了圆⼼和半径那么这个圆就完成了。
同样的道理,椭圆、正⽅形、矩形、圆端矩形,也可以由⼀个中⼼点和⼀个可拖动来改变图形的形状和⼤⼩的点(这⾥我们管这个点叫边缘点)来确定,边缘点的坐标可以直接⽤来确定图形的宽度和⾼度。
⽽在饼、和弦中,边缘点不仅仅是⽤来决定图形的宽度和⾼度,还需要⽤来确定⾓度(与X轴正⽅向的夹⾓)。
最⿇烦的是多边形,因为每点击⼀下就需要绘制⼀个点并且完成连线,所以需要把每个点的坐标从场景传递到图形,然后在图形中完成绘制。
⾃定义功能图元 - 点
点依附于图形之上,所以构造函数中需要传⼊⼀个图形,代表这个点在这个图形上,并且需要初始化点的坐标和类型;
class BPointItem : public QObject, public QAbstractGraphicsShapeItem
{
Q_OBJECT
public:
enum PointType {
Center = 0, // 中⼼点
Edge, // 边缘点(可拖动改变图形的形状、⼤⼩)
Special // 特殊功能点
};
BPointItem(QAbstractGraphicsShapeItem* parent, QPointF p, PointType type);
QPointF getPoint() { return m_point; }
void tPoint(QPointF p) { m_point = p; }
protected:
英语名词virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
virtual void mouMoveEvent(QGraphicsSceneMouEvent *event) override;
删除的英文private:
国际和平日QPointF m_point;
PointType m_type;
};
根据类型不同,绘制的形状也不同。中⼼点是⼀个圆,并且光标是 OpenHandCursor,⽽其他类型的点则是⼀个正⽅形,光标是PointingHandCursor;
当我们移动点的时候,如果是中⼼点则会整个图形⼀起移动,⽽移动边缘点的时候会根据边缘点的坐标来动态改变图形的形状,这⾥代码⽐较多就不贴了。
BPointItem::BPointItem(QAbstractGraphicsShapeItem* parent, QPointF p, PointType type)
: QAbstractGraphicsShapeItem(parent)
twitter
, m_point(p)
, m_type(type)
{
this->tPos(m_point);
this->tFlags(QGraphicsItem::ItemIsSelectable |
QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable);
switch (type) {
ca Center:
this->tCursor(Qt::OpenHandCursor);
break;
ca Edge:
this->tCursor(Qt::PointingHandCursor);
break;
ca Special:
this->tCursor(Qt::PointingHandCursor);
break;
default: break;
}暑假训练营
}
QRectF BPointItem::boundingRect() const
{
return QRectF(-4, -4, 8, 8);
}
void BPointItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
现状翻译
painter->tPen(this->pen());
painter->tBrush(this->brush());
this->tPos(m_point);
switch (m_type) {
ca Center:
painter->drawEllip(-4, -4, 8, 8);
break;
ca Edge:
painter->drawRect(QRectF(-4, -4, 8, 8));
break;
ca Special:
painter->drawRect(QRectF(-4, -4, 8, 8));
break;
default: break;
}
}
void BPointItem::mouMoveEvent(QGraphicsSceneMouEvent *event)
{
if ( event->buttons() == Qt::LeftButton ) {
qreal dx = event->scenePos().x() - event->lastScenePos().x();
qreal dy = event->scenePos().y() - event->lastScenePos().y();
BGraphicsItem* item = static_cast<BGraphicsItem *>(this->parentItem());
BGraphicsItem::ItemType itemType = item->getType();
switch (m_type) {
ca Center: {
item->moveBy(dx, dy);
this->scene()->update();
} break;
ca Edge: {
略...
} break;
ca Special: {
略...
} break;
default: break;
}
}
}
⾃定义图元基类
定义了⼀个图元基类,每⼀个图元都⾄少需要⼀个中⼼点、⼀个边缘点和图元类型。重写了焦点事件,当获得焦点时会改变颜⾊;
class BGraphicsItem : public QObject, public QAbstractGraphicsShapeItem {
Q_OBJECT
public:
enum ItemType {
Circle = 0, // 圆
Ellip, // 椭圆
Concentric_Circle, // 同⼼圆
Pie, // 饼
Chord, // 和弦
Rectangle, // 矩形
Square, // 正⽅形
达姆弹
Polygon, // 多边形
Round_End_Rectangle,// 圆端矩形
Rounded_Rectangle // 圆⾓矩形
};
QPointF getCenter() { return m_center; }
void tCenter(QPointF p) { m_center = p; }
QPointF getEdge() { return m_edge; }
void tEdge(QPointF p) { m_edge = p; }
ItemType getType() { return m_type; }
protected:
BGraphicsItem(QPointF center, QPointF edge, ItemType type);
virtual void focusInEvent(QFocusEvent *event) override;
virtual void focusOutEvent(QFocusEvent *event) override;
protected:
QPointF m_center;
QPointF m_edge;
ItemType m_type;
BPointItemList m_pointList;
QPen m_pen_isSelected;
QPen m_pen_noSelected;
};
BGraphicsItem::BGraphicsItem(QPointF center, QPointF edge, ItemType type)
: m_center(center), m_edge(edge), m_type(type)
{
m_pen_noSelected.tColor(QColor(0, 160, 230));circuit city
m_pen_noSelected.tWidth(2);
m_pen_isSelected.tColor(QColor(255, 0, 255));
m_pen_isSelected.tWidth(2);
this->tPen(m_pen_noSelected);
this->tFlags(QGraphicsItem::ItemIsSelectable |
QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable);
}
void BGraphicsItem::focusInEvent(QFocusEvent *event)
{
Q_UNUSED(event);必益教育
this->tPen(m_pen_isSelected);
}
void BGraphicsItem::focusOutEvent(QFocusEvent *event)
{bite怎么读
Q_UNUSED(event);
this->tPen(m_pen_noSelected);
}
矩形
以矩形为例来介绍⼀下图元,构造函数参数为中⼼点坐标和矩形的宽、⾼、类型。初始化中⼼点和边缘点之后即可绘制出矩形,重写 paint 函数把矩形的宽和⾼绑定到 m_edge 的坐标,矩形的⼤⼩就由边缘点的坐标决定,当我们拖到边缘点时只需更新 m_edge 的坐标,矩形的形状就能动态改变;
class BRectangle : public BGraphicsItem
{
public:
BRectangle(qreal x, qreal y, qreal width, qreal height, ItemType type);
protected:
virtual QRectF boundingRect() const override;
virtual void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
};