PDA

View Full Version : QPainter::drawText



h123
13th November 2008, 15:40
I am doing following steps;

QPainter p;
p.begin(myGlWidget);
...
// get the width and height from the glcontext
const QGLContext *glcx = myGlWidget->context();
width = glcx->device()->width();
height = glcx->device()->height()
...
// setting some openGL state
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluProject(x, y, z, &m[0][0], &p[0][0], &v[0], &w_x, &w_y, &w_z);
w_y = height - w_y;
// ??? following line does not draw text on glwidget, any reason ???
p.drawText(QPointF(w_x, w_y), QString(text)); =================== (A)
// restoring the openGL state
p.end();

Please let me know why above line (A) didn't rendered the text on glwidget.

Thank you.

fullmetalcoder
13th November 2008, 18:13
why are you mixing QPainter methods and GL calls?

The doc clearly says that :


3D drawing happen through 3 specific virtual protected methods and require GL calls (you may also do 2D there but that's not the point)
2D drawing can be done in paintEvent() as usual WITHOUT any GL calls. QPainter automatically use a GL-based paint engine when operating on a QGLWidget to accelerate rendering so mixing QPainter/GL in paintEvent is both useless and a potential source of errors

http://doc.trolltech.com/4.3/qglwidget.html#details

p.s : use the [ c o d e ] tag to enclose source code you past in a post.

h123
14th November 2008, 02:16
Hi,



QPainter p;
p.begin(myGlWidget);
...
// get the width and height from the glcontext
const QGLContext *glcx = myGlWidget->context();
width = glcx->device()->width();
height = glcx->device()->height()
...
// setting some openGL state
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluProject(x, y, z, &m[0][0], &p[0][0], &v[0], &w_x, &w_y, &w_z);
w_y = height - w_y;
// ??? following line does not draw text on glwidget, any reason ???
p.drawText(QPointF(4.5, -1.6), QString(text)); =================== (A)
p.drawLine(QRect(0, 0, w_x, w_y)); ============== (B)
// restoring the openGL state
p.end();


But when I try with drawLine, it works and displays the diagonal line.
When I tried with drawText worked but it displays the text at very top-left. How can I convert 4.5 and -1.6 into window co-ordinates ?

Thank you.

h123
14th November 2008, 02:43
Hi,

Please igone my previous code...



QPainter p;
p.begin(myGlWidget);
...
// get the width and height from the glcontext
const QGLContext *glcx = myGlWidget->context();
width = glcx->device()->width();
height = glcx->device()->height()
...
// setting some openGL state
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluProject(x, y, z, &m[0][0], &p[0][0], &v[0], &w_x, &w_y, &w_z);
w_y = height - w_y;
// At this point it w_x, w_y should have been in windows
// co-orrdinates... but still the following line draws the text at
// very top-left in glwidget, any reason ???
p.drawText(QPointF(w_x, w_y), QString(text));=========== (A)
p.drawLine(QRect(0, 0, width, height));================ (B)
// restoring the openGL state
p.end();



So here the drawLine works fine and displays the diagonal line.

But drawText displays the text at very top-left of the glwidget.
1) Is it the problem that w_x, w_y not converted into windows co-ordinate?
2) lets say glwidget width x height is 200 x 200, then suppose I want to place the text at x=4.5 and y=-1.6, then how can I convert x, y into window co-ordinates ? any steps ?

Thank you.

nifei
14th November 2008, 05:17
I suppose that you should use:
QGLWdiget : : renderText ( double x, double y, double z, const QString & str, const QFont & font = QFont(), int listBase = 2000 )

and glLines(..), glPoints(...), .etc

nifei
14th November 2008, 05:21
Hi,

Please igone my previous code...



QPainter p;
p.begin(myGlWidget);
...
// get the width and height from the glcontext
const QGLContext *glcx = myGlWidget->context();
width = glcx->device()->width();
height = glcx->device()->height()
...
// setting some openGL state
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluProject(x, y, z, &m[0][0], &p[0][0], &v[0], &w_x, &w_y, &w_z);
w_y = height - w_y;
// At this point it w_x, w_y should have been in windows
// co-orrdinates... but still the following line draws the text at
// very top-left in glwidget, any reason ???
p.drawText(QPointF(w_x, w_y), QString(text));=========== (A)
p.drawLine(QRect(0, 0, width, height));================ (B)
// restoring the openGL state
p.end();



So here the drawLine works fine and displays the diagonal line.

But drawText displays the text at very top-left of the glwidget.
1) Is it the problem that w_x, w_y not converted into windows co-ordinate?
2) lets say glwidget width x height is 200 x 200, then suppose I want to place the text at x=4.5 and y=-1.6, then how can I convert x, y into window co-ordinates ? any steps ?

Thank you.

where did you put these code? gl***() could only be called in QGLWidet's members and
QPainter p;
p.begin(myGlWidget);
is obvisouly cannot be there. i'm wondering what does painter do?

fullmetalcoder
14th November 2008, 12:20
actually QGLWidget specialized methods that initialize GL context and render things using GL commands (I mean the methods where you can and are supposed to do this) are most likely called from the default paintEvent() which makes it possible to initialize a QPainter in them but, again, it is NOT the right thing(tm) to do...

If all you need is simple 2D drawing QGLWidget does all the needed GL calls under the hood when you simply use QPainter inside the paintEvent().

If you need some complex rendering to be done use these methods instead (do not touch the painEvent()) as recommended by the docs :

paintGL (http://doc.trolltech.com/4.3/qglwidget.html#paintGL)() - Renders the OpenGL scene. Gets called whenever the widget needs to be updated.
resizeGL (http://doc.trolltech.com/4.3/qglwidget.html#resizeGL)() - Sets up the OpenGL viewport, projection, etc. Gets called whenever the the widget has been resized (and also when it is shown for the first time because all newly created widgets get a resize event automatically).
initializeGL (http://doc.trolltech.com/4.3/qglwidget.html#initializeGL)() - Sets up the OpenGL rendering context, defines display lists, etc. Gets called once before the first time resizeGL (http://doc.trolltech.com/4.3/qglwidget.html#resizeGL)() or paintGL (http://doc.trolltech.com/4.3/qglwidget.html#paintGL)() is called.

And avoid mixing GL calls with QPainter. Even if it works it is USELESS and a clear design failure... Anything QPainter does is done using GL commands so if you're doing advanced GL rendering you certainly know how to do some simple 2D painting directly using GL or you use some of the convenience methods of QGLWidget (eg QGLWidget::renderText() (http://doc.trolltech.com/latest/qglwidget.html#renderText))

Last but not least, GL coordinates and windows coordinates are not the same : Windows use a right/down base whose origin is at the top left corner while GL use a right/up base whose origin is a the center of the rendering context. Going from one to another requires the composition of two basic transforms : translation and symetry of axe (Ox)

h123
14th November 2008, 17:54
Hi fullmetalcoder,

Thank you for your detailed explanation.

> Anything QPainter does is done using GL commands so if you're
> doing advanced GL rendering you certainly know how to do some
> simple 2D painting
The basic requirement is to draw the text on the QGLWidget.

I have already done experiments on QGLWidget::renderText(), but it is tooooo slow, while performing rotation with text.

Then I looked into the internals of the renderText.
I looked into the Qt443 code and found that in renderText() it uses the QPainter::drawText(). So I am trying to simulate the same code in my program, but I am facing this problem.


Can you please let me know...
1) how can I optimize the performance of renderText()?
2) can I get better performance if I use QPainter::drawText on QGLWidget?
3) can I get still better performance if I use QPaintEngine::drawTextItem() on QGLWidget, pl. provide example.

And finally I don't won't to go with third-party libraries like FontGL/FTGL.

Thank you.

fullmetalcoder
15th November 2008, 10:10
the performances of QLWidget depends of several factors that do not affect (or not as noticably) regular widgets :


GPU
OpenGL implementation/ GPU drivers
AA settings

I don't have Qt source code on my box atm so I can't comment about renderText()/drawText() though there should not be a huge difference.

As for coordinate transform this should do :

QPointF GLToWindow(const QPointF& p, int width, int height)
{
return QPointF(width - p.x(), height - p.y());
}
QPointF WindowToGL(const QPointF& p, int width, int height)
{
return QPointF(width - p.x(), height - p.y());
}
Yes the two functions do exactly the same but having a different name might help to keep the code readable.

So I think the problem actually lies in this line or in any of the preceding lines that setp up the parameters of the function :

gluProject(x, y, z, &m[0][0], &p[0][0], &v[0], &w_x, &w_y, &w_z);