QFont错误使文本适合特定高度

时间:2019-03-02 23:16:01

标签: c++ qt

我需要在QGraphicsView的前景上绘制比例。为此,我创建了一个从其继承并重新实现drawForeground的类(也可以使用具有较高z值的自定义图形项来完成该类,但为确保未在其上绘制任何内容,我决定将{{1 }}是一个更好的解决方案。在这种方法中,我可以根据需要绘制比例尺(带有黑白框的矩形),并且具有所需的行为。但是,我需要按比例显示的标签尺寸计算部分无法正常工作。我的体重秤标签相对于屏幕应始终具有相同的高度。这意味着,当我们放大和缩小时,需要计算字体大小以适合总是10像素高的矩形。计算文本高度是从here

复制的

这是我的课程实现:

标题

drawForeground

Cpp

#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

文本恒定高度或多或少起作用,尽管它不一定总是完全相同的高度,有时它似乎被裁剪了。此外,最重要的错误是,经过一定缩放后,将#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();看)讯息)。

我的问题是:

  1. 如何强制文本高度保持恒定,以使用户在放大/缩小时看不到文本大小变化?
  2. 为什么qDebug在设置了一定的字体磅值后会冻结我的应用程序?我该如何解决?

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

1 个答案:

答案 0 :(得分:1)

调用函数drawForeground时,比例尺已应用于您的 painter

您可以调用painter->resetMatix()将其删除(但是,它将删除包括旋转和剪切在内的所有变换。也许您应该重新计算没有比​​例因子的新矩阵)。

文本将始终以相同的高度绘制。但是,您的 painter 将在“真实”位置绘制文本。您必须将转换应用于QRect才能解决:

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