2016-06-09 11 views
5

Ich bin erforderlich, um Textelemente mit exakte Breite und Höhe der Textinhalte zu erstellen.
Die Höhe des Textes ist die wichtigste Voraussetzung.
Die Position des Textes sollte relativ zum Text selbst sein.Set QGraphicsTextItem Textinhalt der genauen Höhe und Breite

Ich muss auch in der Lage sein, es auf der Leinwand an einer genauen Stelle zu platzieren.

Angenommen, ein (druckbarer) Canvas (auf einem größeren QGraphicsScene), sagen 5 Zoll Breite und 1 Zoll Höhe, sollte mein Text in der Lage sein, oben-unten-links-rechts zu strecken - und auf Leinwand, nicht Teil in austeilen.


Ich bin Unterklasse QGraphicsTextItem für meine Elementart. Ich ändere die Größe, indem ich QTransform() verwende, auf die erforderliche Größe - in Zoll oder mm oder Pixel (72 * in).
Einstellung auch die document() Ränder auf 0, und etwas nach innen (wie QTextBlockFormat Rand) auch auf 0

Ich habe ein setItemSize(QSizeF sz) umgesetzt (mit sz in Pixeln), dass die QGraphicsTextItem nach Bedarf skaliert.
Die sz ist initialisiert mit dem Artikel Grenze rect.
Unter der Annahme, keine Umbruch, einzelne Zeile Text (Multi-Zeile könnte separat gelöst werden, sobald dieses Problem gelöst ist).

Beim Hinzufügen des Elements zum Canvas wird immer noch ein oberer und unterer Rand angezeigt - dies hängt von der Schriftart ab.
Ich zeichnete ein Rechteck um das Objekt, um es zu sehen.
Die Abstände zwischen oben und unten hängen von der Schriftauswahl ab.


Ich habe versucht, Font-Metriken zu verwenden, um diese Abstände zu ermitteln (in paint() Ich habe Linien auf sich gezogen, um zu versuchen, die Position und Rechteck der Text passt, in dem bestimmen).

Ich wäre glücklich, zumindest in der Lage zu sein, korrekte Größe für Großbuchstaben, keine Akzente oder Sonderzeichen Fonts zu bestimmen (es wäre ein Anfang, obwohl natürlich ich in der Lage sein, alle Zeichen zu verwenden).
Aber zumindest eine Möglichkeit, die Größe und die Position (bezogen auf die (0,0) von Artikel) des Textinhalts selbst im einfachsten Fall zu bestimmen .....

Die Fontmetriken tightBoundingRect() scheint die genaueste für die Größe, aber es scheint unmöglich zu sein, seine Position zu bestimmen, so dass ich meine Artikel irgendwie richtig erstellen kann und sie vielleicht auf die Leinwand anpassen kann.


Hier sind einige Beispiele für meinen Kampf zumindest genaue Größe und Position des Textes, bezogen auf das (0,0) des Artikels zu bestimmen (unter der Annahme, dass, wenn ich das tue, ich bin in der Lage zu belichten, dass Info nach außen oder die Verschiebung in den Artikel bei der Größenänderung umwandeln).
Beachten Sie, dass die Größe des Textes, der von den Schriftmetriken beworben wird, nicht immer den Text abdeckt, und für verschiedene Schriftarten bin ich nicht in der Lage, das enge umgebende Rechteck (Magenta) um den Text selbst zu positionieren. (Ich habe mehrere Vermutungen gemacht, der folgende Code ist nur einer - die Zeilen versuchen, unterschiedliche Schriftgrößen anzuzeigen).

enter image description here

die oben waren Experimente in Farbe Funktion des Textelementes vererben QGraphicsTextItem:

void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) 
{ 
    // draw text 
    QGraphicsTextItem::paint(painter, option, widget); 

    QPen p; 
    p.setWidthF(0); 
    QFontMetricsF fm(this->font()); 
    qreal ascent = fm.ascent(), 
      descent = fm.descent(), 
      hheight = fm.height(); 
    QRectF r = QGraphicsTextItem::boundingRect(); 
    QRectF rFont= fm.tightBoundingRect(toPlainText()); 

    qreal xmax = r.right(); 

    painter->save(); 
    painter->setBrush(Qt::NoBrush); 

    // where is "ascent + descent" 
    p.setColor(Qt::green); 
    painter->setPen(p); 
    painter->drawLine(QPointF(2, ascent), QPointF(2, ascent + descent)); 
    painter->drawLine(QPointF(2, ascent + descent), QPointF(xmax/2, ascent + descent)); 

    // where is "height" 
    p.setColor(Qt::red); 
    painter->setPen(p); 
    painter->drawLine(QPointF(xmax/2, 0), QPointF(xmax/2, hheight)); 
    painter->drawLine(QPointF(xmax/2, ascent + descent), QPointF(xmax, ascent + descent)); 

    // where is "ascent" 
    p.setColor(Qt::yellow); 
    painter->setPen(p); 
    painter->drawLine(QPointF(6, 0), QPointF(6, ascent)); 
    painter->drawLine(QPointF(6, ascent), QPointF(xmax, ascent)); 

    // something that may look like top of the text 
    p.setColor(Qt::blue); 
    painter->setPen(p); 
    qreal yyy = ascent + rFont.y() + 1; 
    painter->drawLine(QPointF(5, yyy), QPointF(xmax, yyy)); 

    // this should be useful... should be the natural offset 
    qreal yoffset = (r.height() - rFont.height())/2; 
// qDebug() << yoffset << r << rFont; 
    //qreal y0 = (r.height() - fm.height())/2; 

    p.setColor(Qt::darkGreen); 
    painter->drawEllipse(10, yoffset, 1, 1); 

    // where is the font rect 
    p.setColor(Qt::magenta); 
    painter->setPen(p); 
    yoffset = (r.height() + rFont.height())/2; 
    painter->translate(0, yoffset); 
    painter->drawRect(rFont); 
    painter->restore(); 
} 

Ich habe versucht, auch nicht QGraphicsTextItem verwenden, aber Farbe Text in einem Rechteck. Das Gleiche passiert.

(Qt 4.7 - 5.x)

+0

Bitte geben Sie einen Screenshot, was Sie sehen und was Sie erwarten. Ich habe das Gefühl, dass du mit Aufstieg oder etwas ähnlichem kämpfst. –

+0

@MarekR - Ich habe meine Funktion zur Berechnung der Position und Screenshots in meiner Antwort unten hinzugefügt. – Thalia

Antwort

2

Dies ist keine gute Lösung. Dies ist ein Versuch, mein eigenes Problem zu lösen - in einer ersten Iteration - Text mit gegebener Breite und Höhe zu setzen, mit Hilfe von Font-Metriken.

Gründe für die nicht gut zu sein -

  • Auch nach Größe ändern, ist Text kleiner als gewünscht ist, verstehe ich nicht, warum

  • Die Position ist falsch, basierend auf Schriftstil kann der Text über oder unter der Leinwand sein, was bedeutet, dass es abgeschnitten wird.


ich die Größe er von den begrenzenden rect Größe und die Font-Metriken begrenzende rect (I verwendet, um die engen Begrenzungs rect für eine genauere Größe) berechnet, um einen Faktor verwendet wird.

myText->setItemFontSize(12); // If I use font metrics I need to reset text size on every change, because resizing loses font info 
QFontMetricsF fm(myText->font()); 
QRectF fmRect = fm.tightBoundingRect(myText.toPlainText().toUpper()); 
// without toUpper() the size is too small - even so it is a bit small 
// I read tightBoundingRect is slow - but boundingRect and height and ascent all give values that result in even smaller size 
//qreal absH = fm.ascent(); 
qreal absH = fmRect.height(); 
qreal absW = fmRect.width(); 
qreal absHeightRatio = myText->getItemSize().height()/absH; 
qreal absWidthRatio = myText->getItemSize().width()/absW; 

Dann Einstellung Größe:

myText->setItemSize(QSizeF(absWidthRatio * textLength, absHeightRatio * fontHeight)); 
// This function scales the `QTransform` on item 
// but since I request a final position dependent on item size 
// (including blank space around it) - it has no chance of being accurate..... 
// This is where my next effort will go, figuring out how to get rid of the fluff 
// around the item inside the scaling 

Die Funktion Position für die Einstellung: versuchen, Text zu zentrieren:

// leftShift = 10, rightShift = 10 in example 
myText->setPos(0,0); 
QRectF r = myText->mapToScene(myText->boundingRect()).boundingRect(); 
QSizeF sz = r.size(); 
qreal w = sz.width(); 
qreal h = sz.height(); 
qreal cx = (m_docLength - w + leftShift - rightShift)/2 - r.left(); 
qreal cy = (m_docHeight - h)/2 - r.top(); 
myText->setPos(cx, cy); 

Die folgenden Bilder sind für Fontheight = m_docHeight -

Erwünschte :
- entweder die gesamte Textgröße (Aufstieg + Abstieg) entspricht Doc-Höhe, und Text wird vertikal basierend auf Inhalt zentriert
- oder der Großbuchstabe Text entspricht Doc-Höhe und der Abstieg ist unter Dokument (Text zentriert nur in Großbuchstaben) - dies würde einfacher scheinen basiert wie QGraphicsTextItem scheint es

Actual zu positionieren:
- der Text kleiner keine Materie, welche Parameter ich Skala verwenden und oben mittig Fall textbasierte

enter image description here

wie oben gezeigt - Ich h ave keine Idee, wie ich vertikal basierend auf Inhalt zentrieren könnte (so für Rand-zu-Rand-Text würde der Abstieg passen) - und stattdessen, alles, was ich wirklich will, ist Rand-zu-Rand-Großbuchstaben, aber ich kann ' Das scheinen wir erreichen zu können.

Oh, und das sind für Arial Schriftart - eine der am besten benommenen. Andere Schriftarten springen überall über oder unter der Leinwand.Und für einige Schriftarten ist der resultierende Text tatsächlich kleiner - was für mich unerklärlich ist, denn wie kann das eng umgrenzte Rechteck kleiner sein als das umrahmende Rechteck?

Trotzdem ist das soweit ich dazu gekommen bin Text so nahe wie "wahr" Größe und auf einer Leinwand, die seiner Größe entspricht platziert.

+2

Versuchen Sie 'QFontMetricsF' anstelle von' QFontMetrics' zu verwenden. Ich hatte vorher schon ein paar Albträume davon. – p4plus2

+0

@ p4plus2 - Ich habe es ersetzt, aber ich sehe keine Veränderung. – Thalia