QGraphicsScene如何绘制网格

为了获得snap-to-grid功能,我们需要执行以下操作

  • 子类化QGraphicsScene , 重写drawBackground()虚函数
  • 子类化QGraphicsItem , 重写itemChange()
  • 重写继承QGraphicsItem 子类的mousePressEvent()
void Scene::drawBackground(QPainter *painter, const QRectF &rect)
    QPen pen;
    painter->setPen(pen);
/*计算起始位置*/
    qreal left = int(rect.left()) - (int(rect.left()) % gridSize);
    qreal top = int(rect.top()) - (int(rect.top()) % gridSize);
    QVector<QPointF> points;
    /*保存所有点位*/
    for (qreal x = left; x < rect.right(); x += gridSize){
        for (qreal y = top; y < rect.bottom(); y += gridSize){
            points.append(QPointF(x,y));
    /*绘制所有的点位*/
    painter->drawPoints(points.data(), points.size());

item与网格对齐

子类化QGraphicsRectItem

class CustomRectItem : public QGraphicsRectItem
public:
    CustomRectItem(const QRect& rect, QGraphicsItem* parent,
                                   QGraphicsScene* scene);
protected:
    QVariant itemChange(GraphicsItemChange change,
                        const QVariant &value);

启用item的可移动可选中可变化属性

CustomRectItem::CustomRectItem(const QRect& rect, QGraphicsItem* parent,
                               QGraphicsScene* scene):
    QGraphicsRectItem(rect, parent, scene)
    setFlags(QGraphicsItem::ItemIsSelectable |
            QGraphicsItem::ItemIsMovable |
            QGraphicsItem::ItemSendsGeometryChanges);

重写itemChange()
核心算法, 计算最近的网格点的坐标
qreal xV = round(newPos.x()/gridSize)*gridSize;
qreal yV = round(newPos.y()/gridSize)*gridSize;
return QPointF(xV, yV);

QVariant CustomRectItem::itemChange(GraphicsItemChange change,
const QVariant &value)
/*不返回原始位置而是返回最近的网格点*/
    if (change == QGraphicsItem::ItemPositionChange && scene()) {
        QPointF newPos = value.toPointF();
        if(QApplication::mouseButtons() == Qt::LeftButton &&
                qobject_cast<Scene*> (scene())){
            Scene* customScene = qobject_cast<Scene*> (scene());
            int gridSize = customScene->getGridSize();
            qreal xV = round(newPos.x()/gridSize)*gridSize;
            qreal yV = round(newPos.y()/gridSize)*gridSize;
            return QPointF(xV, yV);
            return newPos;
        return QGraphicsItem::itemChange(change, value);

移动时按网格来移动

class CustomRectItem : public QGraphicsRectItem
public:
    CustomRectItem(const QRect& rect, QGraphicsItem* parent,
                                   QGraphicsScene* scene);
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    QVariant itemChange(GraphicsItemChange change,
    const QVariant &value);
private:
    QPointF offset;//item与其最近左上角坐标的偏移量
    QPointF computeTopLeftGridPoint(const QPointF &pointP); //用于捕获到pointP最近的左上角网格点
void CustomRectItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
    offset = pos() - computeTopLeftGridPoint(pos());
    QGraphicsRectItem::mousePressEvent(event);
QPointF CustomRectItem::computeTopLeftGridPoint(const QPointF& pointP){
    Scene* customScene = qobject_cast<Scene*> (scene());
    int gridSize = customScene->getGridSize();
    qreal xV = floor(pointP.x()/gridSize)*gridSize;
    qreal yV = floor(pointP.y()/gridSize)*gridSize;
    return QPointF(xV, yV);

重写itemChange

QVariant CustomRectItem::itemChange(GraphicsItemChange change,
const QVariant &value)
    if (change == ItemPositionChange && scene()) {
        QPointF newPos = value.toPointF();
        if(QApplication::mouseButtons() == Qt::LeftButton &&
            qobject_cast<Scene*> (scene())){
                QPointF closestPoint = computeTopLeftGridPoint(newPos);
                return  closestPoint+=offset;
                /*每次移动都返回当前点击位置与最近的左上角网格点的偏移量*/
            return newPos;
        return QGraphicsItem::itemChange(change, value);
				
Qt提供了一个叫做Qt3DRender::QGeometry的类,可以用来创建三维几何形体。你可以使用这个类来创建一个网格,并使用Qt3DRender::QAttribute来定义每个顶点的坐标、法向量和纹理坐标。 你可以使用Qt3DRender::QGeometryRenderer来渲染你创建的几何体,并使用Qt3DCore::QTransform来控制它的变换。 下面是一个简单的例子,展示了如...
文章目录1. 平移2. 改变尺寸3. 旋转 我们在使用QGraphicsView框架的时候,经常需要自定义QGraphicsItem,并且需要实现Item的平移、改变大小和旋转的效果。接下来介绍他们的一种实现方式 1. 平移 平移效果如下图所示: 实现方式有两种方法: 使用QGraphicsItem本身的移动标志实现。 this->setFlag(QGraphicsItem::Ite...
这篇文章主要阐述了如何使用Qt在像素级别上对图像进行操作,并实现了一些图像效果,这些效果主要有:灰度,模糊,锐化,添加相框,金属质感,改变图像饱和度,亮度还有白平衡。 scanLine 返回某一行数据,转换为QRgb指针可进行直接有效的像素存取操作。 一、QImage、QPixmap、QPicture区别 QBitmap:存储单色的图像,比如遮罩 QPicture:...
刚刚开始想学习Qt,不是很了解,做居中操作的时候看了很多大佬的写法不是非常理解,这里按照自己的理解写的比较简单的实现,具体需要boundingRect()函数获取宽度信息,就可以以给定参数定位。 二话不说,线上代码: QGraphicsTextItem* MainWindow::createTextItem(QString text, int fontSize, int alignState, QPointF pos) 0 ------- align left
QGraphicsTextItem类可以放到QGraphicsScene或者QGraphicsItem上,用来显示格式化的文本内容,如HTML,当然纯文本也可以显示。如果只是显示纯文本,可以使用QGraphicsSimpleTextItem类。 下面的内容都以QGraphicsTextItem作为例子。 这段代码展示了如何使用QGraphicsTextItem: # -*- coding: ...