首页 > 其他分享 >QGraphicsItem::paint()中文字绘制与缩放

QGraphicsItem::paint()中文字绘制与缩放

时间:2022-12-17 15:23:08浏览次数:47  
标签:item 缩放 paint curRect QGraphicsItem 绘制 painter

需求

在QGraphicsRectItem上绘制文字,有下述要求:

  1. 文字能够随着Item的尺寸的变化而缩放
  2. 若增加文字则要按照拉伸或者压缩后的比例增加或者删除文字

实现思路

  实现文字的缩放只能通过painter.scale(sx,sy)缩放坐标系,从而将文字绘制到固定区域上。需要注意两点:

  1. 缩放比例的计算
      利用QPainter->fontMetrics()计算文本的宽度和高度,并与Item->rect()的宽度和高度作比就是缩放的比例。
  2. drawText绘制区域以及对齐方式的设置
      关于绘制大小。drawText(QRectF rect, QString text)中绘制区域rect,与当前Item->rect()大小并不相等,绘制区域rect与缩放没有关系,缩放只是视觉上呈现出来的文字占用的区域增加或者缩小,但是实际上的绘制区域rect仍然应该是QPainter->fontMetrics()得到的宽高。
      关于绘制原点。QGraphicsItem::paint中绘制原点为Item的局部坐标系的原点,和QGraphicsItem在局部坐标系中的位置无关。因此若要将文字绘制到矩形上,或者移动Item,将矩形在局部坐标系中的位置转移到pos上,或者每次都要获取Item在局部坐标系的坐标,而后将painter移动到对应的位置。
      对齐方式的设置和缩放的位置有关。缩放是以坐标原点为缩放中心进行缩放的,通过translate可平移坐标系,在缩放过程中,坐标系原点在Item中的相对位置不发生变化,但是其他的点都会发生变化。(就像把伞撑开,从垂直方向看,就中心点的位置不变,而其他点的位置都会变化,可将其看做以伞轴为中心的放大)

实现代码

  1. 初始化设置
    设置item的位置和大小;三个按钮用于移动item的pos和rect。
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QGraphicsScene * scene = new QGraphicsScene;
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setSceneRect(0, 0, 1000, 1000);
    ui->graphicsView->setAlignment(Qt::AlignLeft|Qt::AlignTop);

    item = new MyRect;
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setFlag(QGraphicsItem::ItemIsSelectable);
    item->setPos(50,40);//设置item的位置和大小
    item->setRect(0, 0, 100, 100);

    ui->graphicsView->scene()->addItem(item);
    ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}

void Widget::on_pushButton_clicked()
{
    item->setRect(20,20,50,200);
}

void Widget::on_pushButton_2_clicked()
{
    item->setPos(100, 100);
    item->setRect(100,10,50,50);
}

void Widget::on_pushButton_3_clicked()
{
    item->setRect(10,150,150,20);
}

  1. QGraphicsItem::paint()
void MyRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->save();//很必要!执行QGraphicsItem::paint要恢复原本的paint
    QString text = "未定义";
    int size = 24;
    QRectF curRect = this->rect();

    QFont font;
    font.setWeight(75);
    font.setFamily("Microsoft YaHei");
    font.setPixelSize(size);
    painter->setFont(font);

    painter->drawLine(0, 0, 200, 0);//绘制局部坐标系,用于观察
    painter->drawText(200, -2, "x");
    painter->drawLine(0, 0, 0, 200);
    painter->drawText(-2, 200, "y");

    QFontMetrics fm = painter->fontMetrics();//计算文本的高度和宽度
    qreal height = fm.height();
    qreal width = fm.horizontalAdvance(text);
    qreal sx = curRect.width() * 1.0 / width;//计算缩放比例
    qreal sy = curRect.height() * 1.0 / height;

    painter->translate(curRect.x(), curRect.y());//重点!由于Item可能不在原点处,因此需要先将坐标系平移到对应位置,缩放后再移动回来,因为缩放时坐标原点不动
    painter->scale(sx, sy);
    painter->translate(-curRect.x(), -curRect.y());

    QRectF newRect = curRect;//重点!设置绘制区域,绘制位置仍然是item的坐标,但是大小应该仍然是文本原本的大小,而后经过缩放正好装在item中
    newRect.setWidth(width);
    newRect.setHeight(height);
//    newRect.setWidth(curRect.width() * 1.0 / sx);效果与上面两行代码相同
//    newRect.setHeight(curRect.height() * 1.0 / sy);

    painter->setPen(Qt::red);
    painter->drawText(newRect, text, Qt::AlignLeft|Qt::AlignTop);
    painter->drawRect(newRect);

    painter->restore();//恢复paint

    QGraphicsRectItem::paint(painter, option, widget);
}

标签:item,缩放,paint,curRect,QGraphicsItem,绘制,painter
From: https://www.cnblogs.com/wsw2022/p/16989024.html

相关文章