首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QFont错误将文本拟合成特定高度

QFont错误将文本拟合成特定高度
EN

Stack Overflow用户
提问于 2019-03-02 23:16:01
回答 1查看 208关注 0票数 0

我需要在QGraphicsView的前景上画一个比例。为此,我创建了一个继承它并重新实现drawForeground的类(它也可以使用一个具有高z值的自定义图形项来完成,但为了确保没有在其上绘制,我决定drawForeground是一个更好的解决方案)。在这种方法中,我根据自己的需要绘制比例(带有黑白框的矩形),并且它具有所需的行为。然而,我需要在我的标尺上显示的标签大小的计算部分不起作用。我的标尺的标签在屏幕上应该总是有相同的高度。这意味着,当我们放大和缩小,字体大小需要计算,以适应一个矩形,始终是10像素的高度。计算文本高度是从here复制的

下面是我的类实现:

报头

代码语言:javascript
复制
#ifndef CUSTOMGRAPHICSVIEW_H
#define CUSTOMGRAPHICSVIEW_H

#include <QGraphicsView>

class CustomGraphicsView : public QGraphicsView
{
  Q_OBJECT
public:
  CustomGraphicsView(QWidget* parent = nullptr);

protected:
  virtual void wheelEvent(QWheelEvent* event) override;

  virtual void drawForeground(QPainter* painter, const QRectF& rect);

  void scalePainterFontSizeToFit(QPainter* painter, float heightToFitIn);

  virtual void contextMenuEvent(QContextMenuEvent* event);

  QAction* action_show_text_;
};

#endif  // CUSTOMGRAPHICSVIEW_H

Cpp

代码语言:javascript
复制
#include "customgraphicsview.h"

#include <QAction>
#include <QDebug>
#include <QMenu>
#include <QWheelEvent>

#include <math.h>

CustomGraphicsView::CustomGraphicsView(QWidget* parent) : QGraphicsView(parent)
{
  setScene(new QGraphicsScene);
  action_show_text_ = new QAction("Show text");
  action_show_text_->setCheckable(true);
  action_show_text_->setChecked(false);
}

void CustomGraphicsView::drawForeground(QPainter* painter, const QRectF& rect)
{
  // Select scale
  std::vector<double> steps = { 0.1, 0.15, 0.25, 0.5, 1, 2, 5, 10, 15, 25, 50 };
  qDebug() << "Rect: " << rect.topLeft() << "->" << rect.bottomRight();
  int target_y = 10;
  double step0 = (rect.bottom() - rect.top()) / target_y;
  double step = step0;
  double min_d = 1000000;
  for (size_t i = 0; i < steps.size(); i++)
  {
    if (fabs(steps[i] - step0) < min_d)
    {
      step = steps[i];
      min_d = fabs(steps[i] - step0);
    }
  }
  qDebug() << "Step: " << step;

  // Bottom right scale bar corner
  QPointF aux = mapToScene(QPoint(10, 10)) - rect.topLeft();
  QPointF br = mapToScene(mapFromScene(rect.bottomRight()) - QPoint(10, 10));

  // Draw outside rectangle
  painter->setPen(QPen(Qt::black, step * 0.01, Qt::SolidLine, Qt::SquareCap));
  painter->drawRect(QRectF(br - QPointF(4 * step, aux.y()), br));

  // Draw left half
  painter->fillRect(QRectF(br - QPointF(4 * step, aux.y()), br - QPointF(3 * step, aux.y() / 2)), Qt::black);
  painter->fillRect(QRectF(br - QPointF(4 * step, aux.y() / 2), br - QPointF(3 * step, 0)), Qt::white);

  // Draw right half
  painter->fillRect(QRectF(br - QPointF(3 * step, aux.y()), br - QPointF(2 * step, aux.y() / 2)), Qt::white);
  painter->fillRect(QRectF(br - QPointF(3 * step, aux.y() / 2), br - QPointF(2 * step, 0)), Qt::black);
  painter->fillRect(QRectF(br - QPointF(2 * step, aux.y()), br - QPointF(0, aux.y() / 2)), Qt::black);
  painter->fillRect(QRectF(br - QPointF(2 * step, aux.y() / 2), br), Qt::white);

  // Add texts
  if (action_show_text_->isChecked())
  {
    QRectF rect_text(br - QPointF(5 * step, aux.y() * 2.1), br - QPointF(3 * step, aux.y() * 1.1));
    scalePainterFontSizeToFit(painter, rect_text.height());
    painter->drawText(rect_text, Qt::AlignCenter, QString::number(0));
    rect_text = QRectF(br - QPointF(4 * step, aux.y() * 2.1), br - QPointF(2 * step, aux.y() * 1.1));
    painter->drawText(rect_text, Qt::AlignCenter, QString::number(step));
    rect_text = QRectF(br - QPointF(3 * step, aux.y() * 2.1), br - QPointF(1 * step, aux.y() * 1.1));
    painter->drawText(rect_text, Qt::AlignCenter, QString::number(2 * step));
    rect_text = QRectF(br - QPointF(1 * step, aux.y() * 2.1), br - QPointF(-1 * step, aux.y() * 1.1));
    painter->drawText(rect_text, Qt::AlignCenter, QString::number(4 * step));
  }
}

void CustomGraphicsView::scalePainterFontSizeToFit(QPainter* painter, float heightToFitIn)
{
  float oldFontSize, newFontSize, oldHeight;
  QFont r_font = painter->font();

  // Init
  oldFontSize = r_font.pointSizeF();

  // Loop
  for (int i = 0; i < 3; i++)
  {
    qDebug() << i << "a";
    oldHeight = painter->fontMetrics().boundingRect('D').height();
    qDebug() << i << "b";
    newFontSize = (heightToFitIn / oldHeight) * oldFontSize;
    qDebug() << i << "c";
    r_font.setPointSizeF(newFontSize);
    qDebug() << i << "d";
    painter->setFont(r_font);
    qDebug() << i << "e";
    oldFontSize = newFontSize;
    qDebug() << "OldFontSize=" << oldFontSize << "HtoFitIn=" << heightToFitIn << "  fontHeight=" << oldHeight
             << "newFontSize=" << newFontSize;
  }

  // End
  r_font.setPointSizeF(newFontSize);
  painter->setFont(r_font);
}

void CustomGraphicsView::wheelEvent(QWheelEvent* event)
{
  // if ctrl pressed, use original functionality
  if (event->modifiers() & Qt::ControlModifier)
    QGraphicsView::wheelEvent(event);
  // otherwise, do yours
  else
  {
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    if (event->delta() > 0)
    {
      scale(1.1, 1.1);
    }
    else
    {
      scale(0.9, 0.9);
    }
  }
}

void CustomGraphicsView::contextMenuEvent(QContextMenuEvent* event)
{
  // Create menu
  QMenu menu(this);

  // Add Fit in view
  menu.addAction(action_show_text_);

  // Exectue menu
  menu.exec(event->globalPos());
}

文本常量高度多少起作用,尽管它并不总是完全相同的高度,而且有时看起来是裁剪的。此外,最重要的错误是,经过一定的缩放(将setPointSizeF设置为0.36127 )之后,应用程序会冻结在行oldHeight = painter->fontMetrics().boundingRect('D').height(); (从qDebug消息中看到)。

我的问题是:

  1. 我如何强制我的文本的高度是恒定的,这样用户就不会看到一个文本大小的变化,因为他/她放大/缩小?
  2. 为什么在设置了某个字体点大小之后,oldHeight = painter->fontMetrics().boundingRect('D').height();会冻结我的应用程序?我怎么才能解决这个问题?

要测试示例代码,您必须通过从图形视图的左键激活上下文菜单中的缩放标签来显示它们。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-02 23:59:55

当函数drawForeground被调用时,刻度已经应用于您的画家。

您可以删除调用painter->resetMatix() (但是,它将删除所有转换,包括旋转和剪切)。也许,你应该重新计算一个没有标度因子的新矩阵)。

文字将始终以相同的高度绘制。但是,你的画家会在“真实”的位置上画课文。您必须将转换应用于您的QRect以修复它:

代码语言:javascript
复制
painter->save(); // Save the transformation

QTransform matrix(painter->transform()); // Get the current matrix containing the scale factor

painter->resetMatrix(); // Remove transformations

QRectF rect_text(br - QPointF(5 * step, aux.y() * 2.1), br - QPointF(3 * step, aux.y() * 1.1));
rect_text = matrix.mapRect(rect_text); // Get the position of rect_text with the right scale

painter->drawText(rect_text, Qt::AlignCenter, QString::number(0));

painter->restore(); // Reset the transformation
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54964002

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档