1

QGraphicsTextItemオブジェクトがありQGraphicsSceneます。ユーザーはQGraphicsTextItem、角をドラッグしてオブジェクトを拡大縮小できます。(これを行うために、カスタムの「変換エディター」を使用しています。) ユーザーはQGraphicsTextItem、プロパティ パネルからフォント サイズを変更して、のサイズを変更することもできます。私がやりたいのは、これらを統合して、ユーザーがマウスで角をドラッグしてオブジェクトをスケーリングすると、実際に舞台裏で「結果のオブジェクトをターゲットサイズに合わせて維持するために必要なサイズのフォント」を計算することです倍率は 1.0 ですか?"

私が今行っているのは、オブジェクトを通常どおりにスケーリングし、マウスのスケーリングが完了したらメソッドをQGraphicsItem::mouseMoveEventトリガーすることです。次に、このメソッドはフォントを適切なサイズに変更し、スケールを 1.0 に戻します。FinalizeMapScaleQGraphicsItem::mouseReleaseEvent

機能しているように見える解決策がありますが、私はそれに夢中ではありません。私は 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 はフォントをスケーリングしました。有効なフォント サイズ (テキスト項目に設定されたフォント サイズではなく、ユーザーに表示される) は何ですか? ユーザーが選択して表示する必要があります。新しいフォントサイズの?これは単なる代替手段であり、同様の計算が必要です。

同様の問題があります。他のユニット グラフィック アイテムと同じように、ユニット サイズ (1 ピクセル サイズ) にしたいテキスト アイテムがあります (ユーザーはそれらをスケーリングできます)。どのフォント (setPointSize) を設定する必要がありますか? (また、setTextWidth と setDocumentMargin は何ですか?) この設計の利点は、テキスト アイテムのスケーリングを、グラフィック アイテムの他の形状のスケーリングとは異なる方法で処理する必要がないことです。(しかし、私はまだそれを機能させていません。)

また、ユーザー インターフェイスの問題: ユーザーがフォント サイズを変更すると、アイテムのサイズも変更されますか? それとも、同じサイズのままで、テキストの折り返しが異なり、テキストの末尾に多かれ少なかれ空白スペースが残りますか? ユーザーが新しいテキストを追加すると、すべてのテキストが図形のサイズに収まるようにフォント サイズが変更されますか?それとも、より多くのテキストを収容できるように図形のサイズが大きくなりますか? つまり、フローチャートアプリのようなもの(形状サイズは固定でフォントが縮小する)なのか、ワープロアプリのようなもの(フォントサイズは一定で形状(ページ数)が大きくなるもの)なのか。

于 2011-12-02T14:18:43.007 に答える