2010-07-21 103 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?)這種設計的優點是,你不需要處理文本項的縮放比任何其他形狀的圖形項縮放。 (但我還沒有工作。)

此外,用戶界面的問題:如果用戶更改字體大小,該項目更改大小?還是它保持相同的大小和文本換行不同,在文本的末尾留下更多或更少的空白空間?當用戶添加新文本時,字體大小是否發生變化,以便所有文本都符合形狀的大小,或者形狀大小是否增長以適應更多文本?換句話說,它更像是一個流程圖應用程序(其中形狀大小是固定的,字體縮小),還是像文字處理器應用程序(字體大小恆定並且形狀(頁數)增長)?