1

QGraphicsTextItemQGraphicsScene. 用户可以QGraphicsTextItem通过拖动角来缩放对象。(我正在使用自定义“转换编辑器”来执行此操作。)用户还可以QGraphicsTextItem通过从属性面板更改字体大小来更改大小。我想做的是统一这些,这样当用户通过用鼠标拖动角来缩放对象时,它实际上是在计算“需要什么大小的字体才能使生成的对象适合目标大小并保持比例因子为 1.0?”

我现在正在做的是让对象正常使用缩放QGraphicsItem::mouseMoveEvent,然后在鼠标缩放完成后触发一个FinalizeMapScale方法。QGraphicsItem::mouseReleaseEvent然后,此方法应将字体更改为适当的大小并将比例设置回 1.0。

我有一个似乎有效的解决方案,但我对此并不着迷。我对 Qt 和 C++ 都比较陌生,所以如果有任何意见或更正,我将不胜感激。

  • 有没有更好的方法来构建整个事情?
  • 是否有已经这样做的 Qt 方法?
  • 我的方法是否在正确的轨道上,但有一些 Qt 或 C++ 错误?

在提交您自己的首选解决方案时,请随时评论我的回答。谢谢!

[编辑]根据评论的要求,这里是缩放代码的基础知识。实际上,我们对此采取了不同的方向,因此不再使用此代码(以及下面的代码)。此代码在方法中,如果在右下角的“热点”中单击鼠标,则mouseMoveEvent先前已将“scaling_”标志设置为true 。mousePressEvent请注意,此代码位于装饰器 QGraphicsItem 中,该装饰器包含指向它正在缩放的​​目标的指针。这种抽象对于我们的项目是必要的,但对于大多数用途来说可能是多余的。

void TransformDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
  ...
  if (scaling_) {
    QGraphicsItem *target_item = target_->AsQGraphicsItem();
    target_item->setTransformOriginPoint(0.0, 0.0);
    QPointF origin_scene = mapToScene(target_item->transformOriginPoint());
    QPointF scale_position_scene = mapToScene(event->pos());
    qreal unscaled_width = target_item->boundingRect().width();
    qreal scale_x = (scale_position_scene.x() - origin_scene.x()) / unscaled_width;
    if (scale_x * unscaled_width < kMinimumSize) {
      scale_x = kMinimumSize / unscaled_width;
    }
    target_item->setScale(scale_x);
  } else {
    QGraphicsObject::mouseMoveEvent(event);
  }
}
4

2 回答 2

1

请不要对 loop-with-exit 构造进行圣战。我们对此感到满意。

void MapTextElement::FinalizeMapScale() {

  // scene_document_width is the width of the text document as it appears in
  // the scene after scaling. After we are finished with this method, we want
  // the document to be as close as possible to this width with a scale of 1.0.
  qreal scene_document_width = document()->size().width() * scale();

  QString text = toPlainText();

  // Once the difference between scene_document_width and the calculated width
  // is below this value, we accept the new font size.
  const qreal acceptable_delta = 1.0;

  // If the difference between scene_document_width and the calculated width is
  // more than this value, we guess at the new font size by calculating a new
  // scale factor. Once it is beneath this value, we creep up (or down) by tiny
  // increments. Without this, we would sometimes incur long "back and forth"
  // loops when using the scale factor.
  const qreal creep_delta = 8.0;
  const qreal creep_increment = 0.1;

  QScopedPointer<QTextDocument> test_document(document()->clone());
  QFont new_font = this->font();
  qreal delta = 0.0;

  // To prevent infinite loops, we store the font size values that we try.
  // Because of the unpredictable (at least to me) relationship between font
  // point size and rendering size, this was the only way I could get it to
  // work reliably.
  QList<qreal> attempted_font_sizes;

  while (true) {

    test_document->setDefaultFont(new_font);
    delta = scene_document_width - test_document->size().width();

    if (std::abs(delta) <= acceptable_delta ||
        attempted_font_sizes.contains(new_font.pointSizeF())) {
      break;
    }

    attempted_font_sizes.append(new_font.pointSizeF());

    qreal new_font_size = 0.0;
    if (std::abs(delta) <= creep_delta) {
      new_font_size = delta > 0.0 ? new_font.pointSizeF() + creep_increment
                                  : new_font.pointSizeF() - creep_increment;
    } else {
      new_font_size = new_font.pointSizeF()
                      * scene_document_width
                      / test_document->size().width();
    }
    new_font.setPointSizeF(new_font_size);
  }

  this->setFont(new_font);
  this->setScale(1.0);
}
于 2010-07-21T17:31:55.333 回答
0

另一种看待问题的方法是:Qt 已经缩放了字体,我需要向用户显示的有效字体大小是多少(在用户看来,而不是在文本项中设置的字体大小)作为他们的选择的新字体大小?这只是一种选择,您仍然需要类似于您的计算。

我有一个类似的问题。我有一个文本项,我想像我的其他单位图形项一样成为单位大小(一个像素大小)(然后用户可以缩放它们。)需要设置什么字体(setPointSize)?(还有什么 setTextWidth 和什么 setDocumentMargin?)这种设计的优点是您不需要将文本项的缩放与任何其他形状的图形项的缩放区别对待。(但我还没有让它工作。)

此外,用户界面问题:如果用户更改字体大小,项目是否会更改大小?还是它保持相同的大小并且文本换行方式不同,在文本末尾留下或多或少的空白?当用户添加新文本时,字体大小会发生变化以使所有文本都适合形状大小,还是形状大小会增大以容纳更多文本?换句话说,它更像是一个流程图应用程序(形状大小固定而字体缩小),还是更像文字处理器应用程序(字体大小恒定而形状(页数)增长?

于 2011-12-02T14:18:43.007 回答