2012-07-12 11 views
7

मेरे पास एक QGraphicsTextItem है जो QGraphicsItem पर अभिभावित है। मैं QGraphicsTextItem को हमेशा QGraphicsItem के ऊपर सीधे रहने के लिए चाहता हूं, लेकिन मैं यह भी चाहता हूं कि स्केल फैक्टर 1 से नीचे हो जाने पर पाठ एक ही आकार में बने रहें, यानी पाठ आकार के आकार में रहता है, भले ही मूल ग्राफिक्स आइटम छोटा स्केल किया गया है। मैंने पाया है कि QGraphicsItem::ItemIgnoresTransformations ध्वज को सही करने के लिए जब स्केल कारक 1 से नीचे है, आकार को बनाए रखने के लिए चाल है।QGraphicsItem लागू करने के बाद सापेक्ष बच्चे की स्थिति को बनाए रखना :: आइटम इग्निर्स ट्रान्सफॉर्मेशन

लेकिन मुझे टेक्स्ट की स्थिति हमेशा QGraphicsItem से ऊपर रहने के लिए एक रास्ता नहीं मिल रहा है। क्या इसे करने का कोई तरीका है? मैंने deviceTransform() फ़ंक्शन का उपयोग करने का प्रयास किया, लेकिन पाठ अभी भी QGraphicsItem से बाहर चला गया क्योंकि मैंने स्क्रॉल किया था। इससे भी बदतर बात यह थी कि कुछ पाठ वस्तुओं ने "चिल्लाया" शुरू किया, यानी उन्होंने लगातार अपनी स्थिति को इतनी थोड़ी-थोड़ी बदलना शुरू कर दिया, ताकि ऐसा लगता है कि वे हिल रहे थे। यदि यह वह कार्य है जिसे मुझे उपयोग करने की आवश्यकता है, तो मुझे लगता है कि मुझे नहीं पता कि इसका सही तरीके से उपयोग कैसे किया जाए।

मैं एक QGraphicsTextItem जोड़ दिया है मेरी QGraphicsItem के निर्माता में:

fTextItem = new QGraphicsTextItem(getName(), this); 
fTextItem->setFlag(QGraphicsItem::ItemIgnoresTransformations); 

यहाँ QGraphicsItem का रंग समारोह से कोड का टुकड़ा है

qreal lod = painter->worldTransform().m22(); 
if(lod <= 1.0) { 
    fTextItem-setFlag(QGraphicsItem::ItemIgnoresTransformations); 
    fTextItem->setPos(fTextItem->deviceTransform(view-viewportTransform()).inverted().map(view->mapFromScene(mapToScene(0,0)))); 
} else { 
    fTextItem->setFlag(QGraphicsItem::ItemIgnoresTransformations, false); 
    fTextItem->setPos(0, 0); 
} 
+0

आप सेट नहीं करना चाहिए QGraphicsTextItem झंडा वस्तुओं QGraphicsItem के बजाय माता पिता परिवर्तन की अनदेखी करने के? – ArmenB

उत्तर

4

अस्वीकरण: इस है कि तुम क्या के लिए overkill हो सकता है करने की कोशिश कर रहे हैं। हमारे पास हमारे प्रोजेक्ट में कुछ अतिरिक्त प्रतिबंध थे जिन्होंने इस समाधान को हमारे लिए सबसे आसान बना दिया।

हमें एक परियोजना में कुछ ऐसा करना पड़ा, और यह हमारे लिए ItemIgnoresTransformations का उपयोग न करने के लिए सबसे आसान हो गया और इसके बजाय अपना स्वयं का परिवर्तन रोल करें। यहां एक मुख्य कार्य है जिसका उपयोग हम किसी विशिष्ट स्थान पर किसी आइटम को चित्रित करने के लिए केवल अनुवाद (कोई स्केलिंग) रूपांतरित करने के लिए करते हैं। आप इसे अपने उपयोग के लिए संशोधित करने में सक्षम हो सकते हैं।

static QTransform GenerateTranslationOnlyTransform(
    const QTransform &original_transform, 
    const QPointF &target_point) { 
    // To draw the unscaled icons, we desire a transform with scaling factors 
    // of 1 and shearing factors of 0 and the appropriate translation such that 
    // our icon center ends up at the same point. According to the 
    // documentation, QTransform transforms a point in the plane to another 
    // point using the following formulas: 
    // x' = m11*x + m21*y + dx 
    // y' = m22*y + m12*x + dy 
    // 
    // For our new transform, m11 and m22 (scaling) are 1, and m21 and m12 
    // (shearing) are 0. Since we want x' and y' to be the same, we have the 
    // following equations: 
    // m11*x + m21*y + dx = x + dx[new] 
    // m22*y + m12*x + dy = y + dy[new] 
    // 
    // Thus, 
    // dx[new] = m11*x - x + m21*y + dx 
    // dy[new] = m22*y - y + m12*x + dy 
    qreal dx = original_transform.m11() * target_point.x() 
      - target_point.x() 
      + original_transform.m21() * target_point.y() 
      + original_transform.m31(); 
    qreal dy = original_transform.m22() * target_point.y() 
      - target_point.y() 
      + original_transform.m12() * target_point.x() 
      + original_transform.m32(); 

    return QTransform::fromTranslate(dx, dy); 
} 

उपयोग करते हैं, ले QPainter को बदलने कि रंग विधि को पारित कर दिया है और की तरह कुछ करने के लिए:

painter->save(); 
painter->setTransform(GenerateTranslationOnlyTransform(painter->transform(), 
                 some_point)); 
// Draw your item. 
painter->restore(); 
+0

इस बिंदु पर मेरी समस्या के लिए ओवरकिल की तरह दिखता है :) लेकिन यदि कोई आसान तरीका नहीं है तो ठोस ग्राउंड अप दृष्टिकोण। आपका बहुत बहुत धन्यवाद! – KD07

+0

मैंने अपने आवेदन में इस कस्टम परिवर्तन का उपयोग करने की कोशिश की। यह अब तक काम करता है कि परिवर्तन चिंता का विषय है लेकिन फिर भी मेरी वस्तु की स्थिति बंद है। मैं माता-पिता के (0,0) बिंदु पर रहने के लिए अपने बच्चे की वस्तु (कस्टम परिवर्तन) चाहता हूं। मैं कुछ_पॉइंट (0,0) के रूप में पास करता हूं। – KD07

6

मेरे सुझाव इस तरह से QGraphicsSimpleTextItem उपवर्ग के लिए है:

class TextItem 
    : public QGraphicsSimpleTextItem 
{ 
public: 
    TextItem(const QString &text) 
     : QGraphicsSimpleTextItem(text) 
    { 

    } 
    void paint(QPainter *painter, 
     const QStyleOptionGraphicsItem *option, QWidget *widget) 
    { 
     painter->translate(boundingRect().topLeft()); 
     QGraphicsSimpleTextItem::paint(painter, option, widget); 
     painter->translate(-boundingRect().topLeft()); 
    } 
    QRectF boundingRect() const 
    { 
     QRectF b = QGraphicsSimpleTextItem::boundingRect(); 
     return QRectF(b.x()-b.width()/2.0, b.y()-b.height()/2.0, 
      b.width(), b.height()); 
    } 
}; 
QGraphicsSimpleTextItem *mText = new TextItem("Item"); 
scene()->addItem(mText); 
mText->setFlag(QGraphicsItem::ItemIgnoresTransformations, true); 
mText->setPos(itemToFollow->pos()); 
+0

ध्यान दें कि KD07 ने 'QGraphicsTextItem' के बारे में पूछा (जो HTML/समृद्ध टेक्स्ट स्वरूपण का समर्थन करता है)। [QGraphicsSimpleTextItem' पर एक और लेना [क्यूटी केंद्र] (http://www.qtcentre.org/threads/51168-QGraphicsTextItem-center-based-coordinates) पर पाया जा सकता है। – handle

0

डेव मैटर के जवाब में जोड़कर, मुझे लगता है कि यह कुछ परिदृश्य में जोड़ने में सहायक होगा, आपको ऑब्जेक्ट के उचित बाउंड आयत (साथ ही आकार) को भी बनाए रखना चाहिए। मेरे लिए, मुझे उचित ऑब्जेक्ट चयन व्यवहार के लिए boundingRect() को थोड़ा संशोधित करने की आवश्यकता है। याद रखें कि ऑब्जेक्ट के बाउंडिंग रेक्ट को स्केल किया जाएगा और सामान्य रूप से बदल दिया जाएगा यदि हम ItemIgnoresTransformations ध्वज का उपयोग नहीं करते हैं। तो हमें दृश्य स्वतंत्रता प्रभाव को बनाए रखने के लिए बाउंडिंगरेक्ट को पुन: सहेजने की भी आवश्यकता है।

दृश्य-स्वतंत्र बाउंडिंग आयत को बनाए रखने के लिए काफी आसान साबित होता है: deviceTransform(m_view->viewportTransform()).inverted().m11() से स्केलिंग कारक को पकड़ें और इस स्थिर को अपने स्थानीय समन्वय बाध्य आयत में गुणा करें। उदाहरण के लिए:

qreal m = this->deviceTransform(m_view->viewportTransform()).inverted().m11(); 
return QRectF(m*(m_shapeX), m*(m_shapeY), 
       m*(m_shapeR), m*(m_shapeR)); 
0

डेव मेटर द्वारा महान उत्तर! मुझे समस्या थी कि मैं विभिन्न ज़ूम स्तरों पर एक अलग पैमाने पर कारक परिभाषित करना चाहता था।इस तरह मैंने किया है:

void MyGraphicsItem::paint(QPainter * painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 
{ 
    //save painter for later operations 
    painter->save(); 
    QTransform originalTransform = painter->transform(); 
    QPointF originalCenter = rect().center(); 
    qreal dx = originalTransform.m11() * originalCenter.x() + originalTransform.m21() * originalCenter.y() + originalTransform.m31(); 
    qreal dy = originalTransform.m22() * originalCenter.y() + originalTransform.m12() * originalCenter.x() + originalTransform.m32(); 
    //normally our target scale factor is 1, meaning the item has keeps its size, regardless of zoom 
    //we adjust the scale factor though when the item is smaller than one pixel in comparison to the background image 
    qreal factor = 1.0; 
    //check if scale factor if bigger that the item size, and thus it occupies less that a pixel in comparision to the background image 
    if (rect().width() < originalTransform.m11()) { 
     //calculate adjusted scale factor 
     factor = originalTransform.m11()/rect().width(); 
    } 
    //adjust position according to scale factor 
    dx -= factor * originalCenter.x(); 
    dy -= factor * originalCenter.y(); 
    //set the new transform for painting 
    painter->setTransform(QTransform::fromScale(factor, factor) * QTransform::fromTranslate(dx, dy)); 
    //now paint... 
    QGraphicsXYZItem::paint(painter, option, widget); 
    //restore original painter 
    painter->restore(); 
} 

आप उस मामले में भी सीमांकन आयत समायोजित करने की आवश्यकता है:

QRectF MyGraphicsItem::boundingRect() const 
{ 
    QRectF rect = QGraphicsEllipseItem::boundingRect(); 
    //this is a bit hackish, let me know if you know another way... 
    if (scene() != NULL && scene()->views().at(0) != NULL) 
    { 
     //get viewport transform 
     QTransform itemTransform = scene()->views().at(0)->transform(); 
     QPointF originalCenter = rect.center(); 
     //calculate back-projected original size of item 
     qreal realSizeX = rect.width()/itemTransform.m11(); 
     qreal realSizeY = rect.height()/itemTransform.m11(); 
     //check if scale factor is bigger that the item size, and thus it occupies less that a pixel in comparison 
     //to the background image and adjust size back to equivalent of 1 pixel 
     realSizeX = realSizeX < 1.0 ? 1.0 : realSizeX; 
     realSizeY = realSizeY < 1.0 ? 1.0 : realSizeY; 
     //set adjusted position and size according to scale factor 
     rect = QRectF(rect.center().x() - realSizeX/2.0, rect.center().y() - realSizeY/2.0, realSizeX, realSizeY); 
    } 
    return rect; 
} 

इस समाधान आइटम काम बहुत अच्छी तरह से में मेरे मामले के साथ।

1) boundingRect() माता पिता की, इस जाओ और दृश्य 2 से मैप) न्यूनतम एक्स और अंक की इस सूची की Y ले:

0

यहाँ एक समाधान मैं बहुत उदारवादी जटिलता के लिए तैयार है है अपने मद का वास्तविक मूल दृश्य में, निर्देशांक 3) सेट बच्चे

Pyside में की स्थिति:

br = parent.mapToScene(parent.boundingRect()) 
    realX = min([item.x() for item in br]) 
    realY = min([item.y() for item in br]) 
    child.setPos(parent.mapFromScene(realX, realY)) #modify according to need 
0

मैं एक और समाधान है, जो किसी भी परिवर्तनों या के साथ खिलवाड़ को शामिल नहीं करता पाया है द्वारा हाथ स्केलिंग/पोजिशनिंग। वहाँ में QGraphicsItem::ItemIgnoresTransformations ध्वज वर्णन एक संकेत है:

QGraphicsItem::ItemIgnoresTransformations

आइटम विरासत में मिला परिवर्तनों (यानी, अपनी स्थिति अभी भी अपने माता-पिता को लंगर डाले है पर ध्यान नहीं देता लेकिन माता-पिता या दृश्य रोटेशन, ज़ूम या कतरनी परिवर्तनों को नजरअंदाज कर दिया जाता है)। [...]

और यह कुंजी है! हमें दो वस्तुओं की आवश्यकता है: एक अभिभावक जो सापेक्ष स्थिति (बिना किसी झंडे के सेट) रखेगा और एक बच्चा आइटम जो माता-पिता के (0,0) बिंदु (QGraphicsItem::ItemIgnoresTransformations ध्वज सेट के साथ) पर चित्रकारी करेगा। इतना ही आसान!

मैं एक एकल वर्ग में इस कार्यक्षमता समझाया गया है - यहाँ कुछ कोड है:

#include <QGraphicsItem> 
#include <QPainter> 

class SampleShape : public QGraphicsItem 
{ 
private: 
    /* This class implements shape drawing */ 
    class SampleShapeImpl : public QGraphicsItem 
    { 
    public: 
     SampleShapeImpl (qreal len, QGraphicsItem *parent = nullptr) 
      : QGraphicsItem(parent), m_len(len) 
     { 
      /* ignore transformations (!) */ 
      setFlag(QGraphicsItem::ItemIgnoresTransformations); 
     } 

     QRectF boundingRect (void) const override 
     { 
      /* sample bounding rectangle */ 
      return QRectF(-m_len, -m_len, m_len*2, m_len*2); 
     } 

     void paint (QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override 
     { 
      /* draw a shape, (0,0) is an anchor */ 
      painter->drawLine(0, -m_len, 0, m_len); 
      painter->drawLine(-m_len, 0, m_len, 0); 
      // ... 
     } 

    private: 
     qreal m_len; // sample shape parameter 
    }; 

public: 
    /* This is actually almost an empty class, you only need to set 
    * a position and pass any parameters to a SampleShapeImpl class. 
    */ 
    SampleShape (qreal x, qreal y, qreal len, QGraphicsItem *parent = nullptr) 
     : QGraphicsItem(parent), m_impl(len, this) // <-- IMPORTANT!!! 
    { 
     /* set position at (x, y), view transformations will apply */ 
     setPos(x, y); 
    } 

    QRectF boundingRect (void) const override 
    { 
     return QRectF(); // it's just a point, no size 
    } 

    void paint (QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override 
    { 
     // empty, drawing is done in SampleShapeImpl 
    } 

private: 
    SampleShapeImpl m_impl; 
}; 
संबंधित मुद्दे