[SOLVED] QGLWidget
-
Hi all,
Today I found a wierd feature of QGLWidget. Can anyone give some explanations?
I am using Mac. For the
@virtual void QGLWidget::resizeGL ( int width, int height )@
function, I found the argument (i.e. width, height) is not the same with the width and height of the QGLWidget instance
i.e.@this->width() and this->height()@
Can anyone tell me why? Thanks.
-
@
void GLWidget::resizeGL(int x, int y) {
qDebug() << x << width() << y << height();
}
@
This gives me always the same results here on Windows 8.
Do you call width()/height() inside resizeGL or somewhere else? Do you use any styling like borders for the QGLWidget?
What kind of error span do you get? Is it constant, random, +/-1 or more? -
[quote author="Chris Kawa" date="1395230891"]@
void GLWidget::resizeGL(int x, int y) {
qDebug() << x << width() << y << height();
}
@
This gives me always the same results here on Windows 8.
Do you call width()/height() inside resizeGL or somewhere else? Do you use any styling like borders for the QGLWidget?
What kind of error span do you get? Is it constant, random, +/-1 or more?[/quote]Hi Chris, thanks for your reply.
I am also doing
@
void GLWidget::resizeGL(int x, int y) {
qDebug() << x << width() << y << height();
}
@and what I got is like following
@
756 378 488 244
@interestingly, x = 2this->width() and y = 2this->height()
Do you know why?
-
By the way, here is what I did:
- I start a Qt Widget Application and then
- Put a QWidget to the QMainWindow UI, and added it to the grid layout
- Promote the QWidget to GLWidget class, which inherit the QGLWidget class
the .cpp code of the GLWidget class is like following.
@
#include "glwidget.h"#include <QDebug>
GLWidget::GLWidget(QWidget *parent) :
QGLWidget(parent)
{
}void GLWidget::initializeGL()
{}
void GLWidget::paintGL()
{}
void GLWidget::resizeGL(int w, int h)
{
qDebug() << w << width() << h << height();
}
@ -
Ah, you wouldn't happen to have one of these retina display thingies, would you? :)
I'm not a Mac expert but from what I know they have this HiDPI mode in which the physical number of pixels is double that reported to the app.
I guess the windowing system (width()/height()) works in that mode while OpenGL context gets access to the real resolution, which makes sense if you think about it.
There was a "blog post":https://blog.qt.digia.com/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/ about it some time ago and it should have more detail than I can give you. It also explains how to get access to the full dpi of your device. -
[quote author="stevewang" date="1395294291"]
interestingly, x = 2this->width() and y = 2this->height()Do you know why?[/quote]
Sounds to me like you're on a Retina display, right? :)
Most Qt APIs operate with logical "points" as units, as opposed to actual physical "pixels". That is in analogy to the Cocoa APIs which also operate with "points" instead of "pixels".
That includes the QPainter and most (all?) QWidget APIs, such as those which let you query/set the size of any given widget.
Under the hood Qt will make sure that those "point" sizes will properly translate to the underlying pixel resolution.
That is also the reason that most Qt pograms will almost run "out of the box" on a Retina display (bitmap based resources off course have to be provided in both "normal" and "retina" resolutions by the application - otherwise icons and images will look "blurry".
Example: when you draw a line with a QPainter from e.g. (100, 200) to (500, 700) those coordinates are considered "points". That line will hence "have the same physical length" on a non-Retina and Retina display. With the only difference that it will have a higher resolution on the Retina display.
Now the above all applies to "abstract paint/widget" interfaces (abstract in the sense that they do not directly let you operate on the actual pixels, at least not with some extra effort on your side). But some graphic APIs - and we are looking at OpenGL now ;) - operate on an even lower level: they operate directly on the framebuffer as provided by the underlying OS, and you have already guessed it: that framebuffer is really measured in pixels now instead of points!
So what Qt - correctly - reports to you is the viewport size in pixels! And on a Retina display that happens to be twice the size (in each dimension) than the widget's size measured in points!
(There is a flag in the underlying NSView which would also scale the OpenGL content correspondingly, but Qt sets it such that the OpenGL draw buffer is always in physical pixel size, or so I understand).
All this is described in the following blog in more detail:
https://blog.qt.digia.com/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
Quote:
"QGlWidget
OpenGL operates in device pixel space. For example, the width and height passed to glViewport should be in device pixels. QGLWidget::resizeGL() gives the width and height in device pixels.
However, QGLWidget::width() is really QWidget::width() which returns a value in device-independent pixels. Resolve it by multiplying with widget->windowHandle()->devicePixelRatio() if needed."
-
ah, that's why.
I understand it now. Thank you Chris and Oliver!