2010-07-21 996 views
1

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

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

我有一个似乎正在工作的解决方案,但我对此并不满意。我对Qt和C++都比较陌生,因此会对任何评论或更正感到欣慰。

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

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

[编辑]根据评论请求,这里是缩放代码的基础知识。实际上,我们对此采取了不同的方向,因此此代码(以及下面的代码)不再使用。该代码位于mouseMoveEvent方法中,如果在右下角的“热点”中单击鼠标,则会在mousePressEvent之前将“scaling_”标志设置为true。请注意,此代码位于装饰器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); 
    } 
} 

回答

1

请不要关于循环与退出结构的圣战。我们对此感到满意。

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); 
} 
+0

我认为用平分算法可能会更好一些,其中一个作为当前字体大小的下限和一个上限是合理的。然后,对于某些N,您应该有一个O(log N)解决方案,依赖于您的数据。 – 2010-07-21 18:07:49

+0

s /'while(true)'/'forever' / – leemes 2012-05-25 16:27:33

0

另一种方式来看待这个问题:Qt拥有缩放字体,什么是有效的字体大小(因为它在用户看来,不是字体大小的文本项中设置),我需要向用户显示他们选择的新字体大小?这只是一种选择,你仍然需要一个类似于你的计算。

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

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