You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现QGraphicsTextItem动态调整大小且保持文本固定在左上角

QGraphicsTextItem动态调整大小修复方案

核心问题说明

你当前的代码仅重写了boundingRect接口,未调整QGraphicsTextItem的绘制逻辑、位置计算逻辑,存在位置漂移、文本对齐错误、内存泄漏三个核心问题,以下是针对性修改:

修复步骤

1. 修复LText类头文件(ltext.h)

新增paint方法重写声明,可选新增shape方法用于碰撞检测优化:

#ifndef LTEXT_H
#define LTEXT_H

#include <QGraphicsTextItem>
#include <QTextDocument>

class LText : public QGraphicsTextItem
{
    Q_OBJECT
    
public:
    enum { Type = UserType + QGraphicsTextItem::Type };

    LText(QGraphicsTextItem *parent = nullptr);
    int type() const override { return Type; }
    QRectF boundingRect() const override;
    QPainterPath shape() const override; // 可选,优化选择检测
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
    void setNeededFlags();
    void updateRect(const QRectF rect);

signals:
    void signalRectChanged();

private:
    QRectF m_rect;
};
#endif // LTEXT_H

2. 修复LText类实现(ltext.cpp)

  • 修复构造函数内存泄漏
  • 修正updateRect的位置计算逻辑,避免拖拽时位置漂移
  • 重写paint方法保证文本始终对齐左上角、超出范围可裁剪
  • 可选重写shape方法优化交互体验
#include <QApplication>
#include <QRectF>
#include <QPainter>
#include <QAbstractTextDocumentLayout>
#include <qmath.h>
#include "ltext.h"

LText::LText(QGraphicsTextItem *parent) : QGraphicsTextItem(parent)
{
    setNeededFlags();
    setPlainText("Text"); // 去掉多余的new QString,修复内存泄漏
    setFont(QFont("Arial", 42));
    m_rect = QRectF();
    // 初始化时同步m_rect为默认大小
    m_rect = QGraphicsTextItem::boundingRect();
    document()->setTextWidth(m_rect.width());
}

QRectF LText::boundingRect() const
{
    return m_rect;
}

QPainterPath LText::shape() const
{
    QPainterPath path;
    path.addRect(m_rect);
    return path;
}

void LText::updateRect(const QRectF rect)
{
    prepareGeometryChange();
    // 拖拽左上角/左/上边框时,需要偏移item位置保证文本左上角固定
    QPointF offset = rect.topLeft();
    if(!offset.isNull()) {
        setPos(pos() + mapToParent(offset));
    }
    // m_rect始终从(0,0)开始,保证文本对齐左上角
    m_rect = QRectF(QPointF(0,0), rect.size());
    // 设置文档宽度,文本超出控件宽度自动换行
    document()->setTextWidth(m_rect.width());
    update();
}

void LText::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    // 裁剪超出控件范围的文本,不需要可以删掉下面一行
    painter->setClipRect(m_rect);
    // 调用默认绘制逻辑,文本从(0,0)开始渲染,始终对齐控件左上角
    QGraphicsTextItem::paint(painter, option, widget);
}

void LText::setNeededFlags()
{
    setFlags(QGraphicsItem::ItemIsSelectable |
            QGraphicsItem::ItemIsMovable |
            QGraphicsItem::ItemSendsGeometryChanges |
            QGraphicsItem::ItemIsFocusable);
}

3. 优化SizeGripItem初始化逻辑

在创建SizeGripItem时传入TextResizer实例即可,示例初始化代码:

LText *textItem = new LText();
scene->addItem(textItem);
new SizeGripItem(new TextResizer(), textItem);

额外优化建议

  • 可以在updateRect中增加最小大小限制,避免控件被拖拽到过小导致文本不可见
  • 如果需要支持缩放文本适配控件大小,可以在updateRect中计算缩放因子,调用painter->scale()实现

内容的提问来源于stack exchange,提问作者webpositive

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 02:24:01