No++

No++

Just another blog on C++, GFX and other stuff

03 Dec 2018

Automatically size/fit a QText2DEntity

The module Qt3D of Qt5.11 has a very useful class/entity in the Extras package: Qt3DExtras::QText2DEntity.

This class/entity allows you to draw text directly into the scene. The problem is that it requires you to set correctly the size of the text rendered beforehand. If you don’t set correctly then the rendering will only draw a part of the text or even won’t draw anything.

Moreover if you want your text to fit a specific size on the screen, then it becomes really tedious.

Here is a little function that allows you to automatically set the best parameters depending on the display size you want.

Code

// The code has been tested successfully with Qt5.11
// "displayWidth" is the width you want for your text
// The function will use the scale value of QTransform of the entity
// If the entity has no QTransform, it will add one.

void text2DEntityFitSize(
  Qt3DExtras::QText2DEntity* text2DEntity,
  float displayWidth)
{
  Q_ASSERT(text2DEntity != nullptr);

  // set best fit width and height
  auto fontMetrics = QFontMetricsF{text2DEntity->font()};
  auto boundingRect = fontMetrics.boundingRect(
    QRectF{},
    Qt::AlignLeft | Qt::AlignTop,
    text2DEntity->text());
  text2DEntity->setWidth(boundingRect.width());
  text2DEntity->setHeight(boundingRect.height());

  // adjust to displayWidth
  auto findTransformComponent =
    [](Qt3DCore::QEntity const* entity) -> Qt3DCore::QTransform*
    {
      auto components = entity->components();
      for(auto& component : components)
      {
        if(auto c = qobject_cast<Qt3DCore::QTransform*>(component))
          return c;
      }
      return nullptr;
    };
  auto transform = findTransformComponent(text2DEntity);
  if(transform == nullptr)
  {
    transform = new Qt3DCore::QTransform{};
    text2DEntity->addComponent(transform);
  }
  transform->setScale(displayWidth / boundingRect.width());
}