Qt5.6: alto soporte de DPI y OpenGL (OpenSceneGraph)
Tengo una aplicación mínima que usaQOpenGLWidget
que integra una biblioteca de contenedor OpenGL (OpenSceneGraph). Estoy tratando de descubrir cómo usar correctamente el soporte Qt5.6 para pantallas de DPI alto cuando trato con contenido OpenGL como el que uso.
Mimain()
La función tiene el siguiente código:
int main(int argc, char** argv)
{
// DPI support is on
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QMainWindow window;
// QOpenGLWidget with OpenSceneGraph content
QtOSGWidget* widget = new QtOSGWidget();
window.setCentralWidget(widget);
window.show();
return app.exec();
}
losQtOSGWidget
se deriva deQOpenGLWidget
con contenido OpenSceneGraph: yo usoosgViewer::GraphicsWindowEmbedded
para representar mi escena simple
Para fusionar OSG con Qt, redefiní el*GL()
métodos:paintGL()
, resizeGL()
yinitializeGL()
. Sigo los documentos de Qt sobre cada uno de los*GL()
los métodos deben contener, es decir:
paintGL()
se asegura de que el visor esté actualizadoresizeGL()
se asegura de que la ventana gráfica se redimensione correctamente (junto con la cámara y la ventana gráfica);initializeGL()
se asegura de que el estado de OpenGL esté inicializado.También redefiní los eventos del mouse Qt para pasar los eventos a OSGCuando ejecuto mi ejemplo en la pantalla de resolución normal, o conQApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
, la escena parece que debería:
Además, cuando manipulo la vista de la cámara, las coordenadas del mouse se capturan correctamente.
Sin embargo, cuando configuro la opción de DPI alto, esto es lo que obtengo:
Las coordenadas del mouse para los eventos también se escalan y no se pasan correctamente al controlador de eventos de OpenSceneGraph.
Como puede ver, Qt no escala el tamaño de la ventana de gráficos. Probablemente se deba a la forma en que configuré el tamaño:
virtual void resizeGL( int width, int height )
{
// resize event is passed to OSG
this->getEventQueue()->windowResize(this->x(), this->y(), width, height);
// graphics window resize
m_graphicsWindow->resized(this->x(), this->y(), width, height);
// camera viewport
osg::Camera* camera = m_viewer->getCamera();
camera->setViewport(0, 0, this->width(), this->height());
}
Ese tamaño no está escalado por Qt. Lo mismo sucede con las coordenadas de eventos del mouse.
Mi pregunta: ¿hay alguna manera de saber a qué tamaño se realizará el escalado para hacerlo?resizeGL()
¿correctamente? ¿O cuál es la forma correcta de lidiar con el problema?
Actualización / Solución usando el escalado a mano: gracias a la respuesta de @AlexanderVX, descubrí la solución de escala. Al principio, necesito conocer algunos valores de referencia de DPI en las dimensiones X e Y. Luego calculo las coordenadas de escala en función de eso y las paso a mi widgetQtOSGWidget
. Entonces, el código de lamain()
tiene que contener:
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
int x = QApplication::desktop()->physicalDpiX();
int y = QApplication::desktop()->physicalDpiY();
// values 284 and 285 are the reference values
double scaleX = 284.0/double(x);
double scaleY = 285.0/double(y);
QMainWindow window;
QtOSGWidget* widget = new QtOSGWidget(scaleX, scaleY, &window);
// etc.
Luego, cada vez que me refiero a las funciones de tamaño que debían pasarse al contenido de OpenSceneGraph (OpenGL), tengo que escalar, por ejemplo:
// resizeGL example
this->getEventQueue()->windowResize(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
// mouse event example
this->getEventQueue()->mouseButtonPress(event->x()*m_scaleX, event->y()*m_scaleY, button);
Actualización final: dado que la plataforma de destino de mi aplicación es Windows 7-10, tiene mucho más sentido seguir con la respuesta propuesta de @AlexanderV (segunda parte), es decir, usarSetProcessDPIAware()
función.