QGraphicsItem画空心图形

本文介绍如何使用Qt的QGraphicsItem类族绘制空心矩形和椭圆,并通过实现shape函数利用QPainterPathStroker达到描边效果。文中提供了具体的代码实现,包括响应鼠标悬停事件以改变描边宽度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用QGraphicsItem类族画出的图形通常都是一个区域(实心的),比如画个圆或者画个矩形。那如果想画个矩形框或者圆形框呢?可以用如下方法,直接上代码

头文件

#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsPathItem>
#include <QGraphicsEllipseItem>

namespace Ui {
class Widget;
}

class MyRectItem : public QGraphicsRectItem
{
public:
    MyRectItem(const QRectF &rect, QGraphicsItem *parent = 0);
    MyRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    QPainterPath shape() const;

protected:
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

private:
    bool isHovered;
};

class MyEllipseItem : public QGraphicsEllipseItem
{
public:
    MyEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0);
    MyEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0);
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    QPainterPath shape() const;

protected:
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

private:
    bool isHovered;
    QRectF rect;
};

源文件

#include <QPainterPath>
#include <QPainterPathStroker>

MyRectItem::MyRectItem(const QRectF &rect, QGraphicsItem *parent)
    : QGraphicsRectItem(rect, parent)
{
    this->isHovered = false;
    setFlag(QGraphicsItem::ItemIsSelectable);
    setAcceptHoverEvents(true);
}

MyRectItem::MyRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
    : QGraphicsRectItem(x, y, w, h, parent)
{
    this->isHovered = false;
    setFlag(QGraphicsItem::ItemIsSelectable);
    setAcceptHoverEvents(true);
}

void MyRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;
    if (this->isSelected())
    {
        pen.setColor(Qt::red);
    }
    else
    {
        pen.setColor(Qt::green);
    }
    if (this->isHovered)
    {
        pen.setWidth(4);
    }
    else
    {
        pen.setWidth(2);
    }
    painter->setPen(pen);
    painter->drawRect(this->boundingRect());
}

QPainterPath MyRectItem::shape() const
{
    QPainterPath temp;
    temp.addRect(this->boundingRect());
    QPainterPathStroker pathStroker;

    QPainterPath path = pathStroker.createStroke(temp);
    return path;
}

void MyRectItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    this->isHovered = true;
    prepareGeometryChange();
}

void MyRectItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    this->isHovered = false;
    prepareGeometryChange();
}

MyEllipseItem::MyEllipseItem(const QRectF &rect, QGraphicsItem *parent)
    : QGraphicsEllipseItem(rect, parent)
{
    this->isHovered = false;
    setFlag(QGraphicsItem::ItemIsSelectable);
    setAcceptHoverEvents(true);
    this->rect = rect;
}

MyEllipseItem::MyEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent)
    : QGraphicsEllipseItem(x, y, w, h, parent)
{
    this->isHovered = false;
    setFlag(QGraphicsItem::ItemIsSelectable);
    setAcceptHoverEvents(true);
    this->rect.setX(x);
    this->rect.setY(y);
    this->rect.setWidth(w);
    this->rect.setHeight(h);
}

QRectF MyEllipseItem::boundingRect() const
{
    return this->rect;
}

void MyEllipseItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    QPen pen;
    if (this->isSelected())
    {
        pen.setColor(Qt::red);
    }
    else
    {
        pen.setColor(Qt::green);
    }
    if (this->isHovered)
    {
        pen.setWidth(4);
    }
    else
    {
        pen.setWidth(2);
    }
    painter->setPen(pen);
    painter->drawEllipse(this->rect);
}

QPainterPath MyEllipseItem::shape() const
{
    QPainterPath temp;
    temp.addEllipse(this->boundingRect());
    QPainterPathStroker pathStroker;

    QPainterPath path = pathStroker.createStroke(temp);
    return path;
}

void MyEllipseItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
    this->isHovered = true;
    prepareGeometryChange();
}

void MyEllipseItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    this->isHovered = false;
    prepareGeometryChange();
}

程序中包括一个矩形类和一个椭圆形类,选中会变色,悬停会变粗。

通过实现shape函数,使用QPainterPathStroker来画图形的外框,这样画出的图像就是空心的。

 

测试代码:

在scene上添加图形:

MyRectItem *itemRect = new MyRectItem(10, 10, 100, 100);
scene->addItem(itemRect);
MyRectItem *item2 = new MyRectItem( 20, 20, 120, 120);
scene->addItem(item2);

MyEllipseItem *item3 = new MyEllipseItem(30, 30, 50, 50);
scene->addItem(item3);

MyEllipseItem *item4 = new MyEllipseItem(50, 50, 100, 80);
scene->addItem(item4);

如图所示,鼠标划过时,框内图形可以选中也可以点击。

C/C++ QT ,mainwindow界面存在两个按钮,一个图形,一个清空所有图形,还有一个graphicsView窗口,graphicsView结合opengl,使用opengl在图像上层上述形状,graphicsView底层要显示一张图像,需要保留graphicsView原有功能,并且是一次性全部上去,且不重叠,请给出完整代码和详细的中文注释以及完整的步骤,头文件和源文件分开给。包含实心三角形、空心三角形、渐变空心三角形,这些三角形在一个类里面实现,每个三角形的三个顶点都由mainwindow界面指定,不需要界面输入,直接给出指定顶点 不存在glPushAttrib函数; 没有与参数列表匹配的构造函数"Q0penGLshaderProgram:Q0penGLshaderProgram" 实例 参数类型为:(OpenGLGraphicsltem*),都说了这里编译无法通过 m_shaderProgram = new QOpenGLShaderProgram(this) "doneCurrent":找不到标识符 makeCurrent":找不到标识符 class"QGraphicsltem"没有成员"ItemUsesOpenGL,QGraphicsltem中只有以下类型enum GraphicsItemFlag { ItemIsMovable = 0x1, ItemIsSelectable = 0x2, ItemIsFocusable = 0x4, ItemClipsToShape = 0x8, ItemClipsChildrenToShape = 0x10, ItemIgnoresTransformations = 0x20, ItemIgnoresParentOpacity = 0x40, ItemDoesntPropagateOpacityToChildren = 0x80, ItemStacksBehindParent = 0x100, ItemUsesExtendedStyleOption = 0x200, ItemHasNoContents = 0x400, ItemSendsGeometryChanges = 0x800, ItemAcceptsInputMethod = 0x1000, ItemNegativeZStacksBehindParent = 0x2000, ItemIsPanel = 0x4000, ItemIsFocusScope = 0x8000, // internal ItemSendsScenePositionChanges = 0x10000, ItemStopsClickFocusPropagation = 0x20000, ItemStopsFocusHandling = 0x40000, ItemContainsChildrenInShape = 0x80000 // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag. }; new OpenGLGraphicsItem(OpenGLGraphicsItem::GradientOutline, vertices, m_scene)这里是错误的,m_scene类型不是QGraphicsItem
07-22
### 关于 `QGraphicsItem` 动实现的方法 为了在 Qt 中为 `QGraphicsItem` 添加动效果,可以利用 `QPropertyAnimation` 类来简化这一过程。下面展示了一个具体的例子,在该实例中,一个矩形项被创建并加入到图形场景 (`QGraphicsScene`) 中;随后通过属性动改变其位置。 #### 创建带有动的 `QGraphicsRectItem` ```cpp #include <QApplication> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsRectItem> #include <QPropertyAnimation> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 初始化场景和视图 QGraphicsScene scene; QGraphicsView view(&scene); // 定义矩形项目及其初始参数 qreal rectWidth = 100; qreal rectHeight = 50; QPointF startPos(0, 0), endPos(200, 200); // 起始位置与结束位置 auto* item = new QGraphicsRectItem(startPos.x(), startPos.y(), rectWidth, rectHeight); scene.addItem(item); // 设置矩形颜色和其他样式 (可选) QBrush brush(Qt::blue); item->setBrush(brush); // 构建动对象并与目标项目的特定属性关联起来 QPropertyAnimation animation(item, "pos"); animation.setDuration(3000); // 持续时间设为三秒 animation.setStartValue(startPos); // 开始值设定为起始位置 animation.setEndValue(endPos); // 结束值设定为目标位置 animation.start(); view.show(); return app.exec(); } ``` 上述代码展示了如何使用 `QPropertyAnimation` 来平滑地移动 `QGraphicsRectItem` 的位置[^1]。此方法同样适用于其他类型的 `QGraphicsItem` 和不同的属性(比如大小、旋转角度等),只需相应调整 `animation` 对象的目标属性即可。 对于更复杂的动需求,还可以考虑组合多个基本动形成序列化或并发执行的效果,这可以通过 `QSequentialAnimationGroup` 或者 `QParallelAnimationGroup` 实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值