How to draw text in QQuickItem?
-
Also, I've looked at the QML
Text
source code, and I'm afraid it is incredibly complicated to draw text the "right" QML way from C++.Hopefully they will provide a useful solution at some point as more people try to create custom QQuickItem's and realise they can't draw text...
-
@Alexey: Have you found a way to render text in the QQuickItem?
-
i also use QQuickPaintedItem, and when i am reimplement the updatePaintNode function, then i get no call for the paint function.
Has anybody solved the problem how to render text in QQuickPaintedItem, or QQuickItem?
I wish there is something like a public QSGTextNode...
-
if you use QQuickPaintedItem, you have to reimplement
@
virtual void paint(QPainter *painter) override;
@This paint method will be called when you invoke update(); method
-
We don't want to use QQuickPaintedItem, We want to use QQuickItem
-
Thats the point, i have reimplemented paint, but i also have reimplemented updatePaintNode...
Maybe i have forgotten something in my reimplementation of updatePaintNode?here is some code:
@MyQuickPaintedItem::MyQuickPaintedItem(QQuickItem *parent)
: QQuickPaintedItem(parent)
, m_xAxisLineCount(500)
{
setFlag(ItemHasContents, true);setRenderTarget(QQuickPaintedItem::FramebufferObject); setPerformanceHint(QQuickPaintedItem::FastFBOResizing); setAntialiasing(true); //setOpaquePainting(true); setMipmap(true); update();
}
QSGNode *MyQuickPaintedItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
QSGGeometryNode *node = 0;
QSGGeometry *geometry = 0;if (!oldNode) { node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_xAxisLineCount * 2); geometry->setLineWidth(1); geometry->setDrawingMode(GL_LINES); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(QColor(255, 0, 0)); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(m_xAxisLineCount * 2); } //qDebug("in updatePaintNode"); QRectF bounds = boundingRect(); QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); int iPlus = 0; for (int i = 0; i <m_xAxisLineCount; ++i) { qreal t = i / qreal(m_xAxisLineCount - 1); vertices[iPlus].set(i, bounds.height() / 2.0); iPlus++;
// QPointF pos_amplitude (t, 0.8 );
// x = bounds.x() + pos_amplitude.x() * bounds.width();
// y = bounds.y() + pos_amplitude.y() * bounds.height();
int height = bounds.height();
int amplitude = rand() % height;
//int amplitude = height;vertices[iPlus].set(i, amplitude); iPlus++; } node->markDirty(QSGNode::DirtyGeometry); return node;
}
void MyQuickPaintedItem::paint(QPainter *painter)
{
// // Pen
QColor randomColor(255,255,60);
QPen myPenRandomColor(randomColor);QRectF bounds = contentsBoundingRect(); // Font QFont font; font.setFamily("Arial"); font.setPixelSize(20); painter->setFont(font); painter->setPen(myPenRandomColor); qDebug("in paint"); painter->drawText(bounds,Qt::AlignCenter, "text");
}@@@@@
so if i take out the reimplementation of updatePaindNode, then the paint function is called...
some Idea how to call booth functions? i want to render text with the QPainter, but draw lines with QSG classes...
-
[quote author="aabc" date="1410860899"]We don't want to use QQuickPaintedItem, We want to use QQuickItem[/quote]
I know, i also want to use QQuickItem, but i think if it is possible, then only with QQuickPaintedItem, if you have an idea, how to render text with QQuickItem, then is perfect, do you have?
greetings Tom
-
reading the qt 5.4 documentation, and maybe the "QOpenGLWidget":http://doc-snapshot.qt-project.org/qt5-5.4/qopenglwidget.html#details
is a good way.
i read, that it is possible to construct a QPainter to draw primitives and render text..."this":http://blog.qt.digia.com/blog/2014/09/10/qt-weekly-19-qopenglwidget/ is also a good article about the good old QGL classes, that i use in the moment... :-( because it is new for me, and unluckily it is old and deprecated...
-
I think i found a way... :-)
here is a blog post how to render with QPainter in an QImage or FBO...
"http://dangelog.wordpress.com/2013/02/10/using-fbos-instead-of-pbuffers-in-qt-5-2/":http://dangelog.wordpress.com/2013/02/10/using-fbos-instead-of-pbuffers-in-qt-5-2/With this you can make a FBO and render text with QPainter in it...
Then you take the FBO or the QImage and create a QSGSimpleTextureNode
"http://qt-project.org/doc/qt-5/qsgsimpletexturenode.html#setTexture":http://qt-project.org/doc/qt-5/qsgsimpletexturenode.html#setTexturewith setTexture you can set the texture to it... and just append the QSGSimpleTextureNode as child to your other node, and thats it :-) i hope...
I will try it on monday... and report if it works...
-
Hi, I'm having this problem also.
I need to render a text on my custom geometry, I don't want to use QPainter because of the blurry text issue in iOS (using QQuickPaintedItem class).
Please advise. TIA.
-
I need it too, because performance.
I looked at Qt's source code (qquicktextnode.cpp) and I found following lines. Perhaps it helps someone...QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color, QQuickText::TextStyle style, const QColor &styleColor, QSGNode *parentNode) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); QRawFont font = glyphs.rawFont(); bool preferNativeGlyphNode = m_useNativeRenderer; if (!preferNativeGlyphNode) { QRawFontPrivate *fontPriv = QRawFontPrivate::get(font); if (fontPriv->fontEngine->hasUnreliableGlyphOutline()) preferNativeGlyphNode = true; else preferNativeGlyphNode = !QFontDatabase().isSmoothlyScalable(font.familyName(), font.styleName()); } QSGGlyphNode *node = sg->sceneGraphContext()->createGlyphNode(sg, preferNativeGlyphNode); node->setOwnerElement(m_ownerElement); node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs); node->setStyle(style); node->setStyleColor(styleColor); node->setColor(color); node->update(); /* We flag the geometry as static, but we never call markVertexDataDirty or markIndexDataDirty on them. This is because all text nodes are discarded when a change occurs. If we start appending/removing from existing geometry, then we also need to start marking the geometry as dirty. */ node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern); node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern); if (parentNode == 0) parentNode = this; parentNode->appendChildNode(node); return node; }
-
I'm making a custom
QQuickItem
too. And it needs to accept a delegate that'll appear in the specific position.So, is it the right solution to expose a
QRect
property and do a QML wrapper that creates and positions that sub-item with aLoader
?Or it's somehow possible to attach other items directly to one of
QSGNode
of a customQQuickItem
? -
@Alexey the only way is to use QQuickText and use private classes