Qt5.6: Unterstützung für hohe DPI und OpenGL (OpenSceneGraph)

Ich habe eine minimale Anwendung, die @ verwendQOpenGLWidget, das eine OpenGL-Wrapper-Bibliothek (OpenSceneGraph) integriert. Ich versuche herauszufinden, wie ich die Qt5.6-Unterstützung für hochauflösende Bildschirme richtig nutzen kann, wenn ich mit OpenGL-Inhalten arbeite, wie ich sie verwende.

Mymain()ie @ -Funktion hat den folgenden Code:

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();
}

DasQtOSGWidget ist abgeleitet vonQOpenGLWidget mit OpenSceneGraph-Inhalten: Ich benutzeosgViewer::GraphicsWindowEmbedded um meine einfache Szene zu rendern.

Um OSG mit Qt zusammenzuführen, definiere ich das @ ne*GL() Methoden:paintGL(), resizeGL() undinitializeGL(). Ich folge den Qt-Dokumenten zu den einzelnen*GL() Methoden sollten enthalten, d.

paintGL() stellt sicher, dass der Viewer aktualisiert wirdresizeGL() stellt sicher, dass die Größe des Grafikfensters korrekt angepasst wird (zusammen mit Kamera und Ansichtsfenster);initializeGL() stellt sicher, dass der OpenGL-Status initialisiert ist.Ich habe auch Qt-Mausereignisse neu definiert, damit die Ereignisse an OSG @ übergeben werde

Wenn ich mein Beispiel auf einem Bildschirm mit normaler Auflösung oder mit @ starQApplication::setAttribute(Qt::AA_DisableHighDpiScaling);, die Szene sieht so aus, wie sie sein sollte:

Auch wenn ich die Kameraansicht bearbeite, werden die Mauskoordinaten korrekt erfasst.

Wenn ich jedoch die Option für hohe DPI einstelle, erhalte ich Folgendes:

Die Mauskoordinaten für Ereignisse werden ebenfalls skaliert und nicht korrekt an die Ereignisbehandlungsroutine von OpenSceneGraph übergeben.

Wie Sie sehen, wird die Größe des Grafikfensters nicht durch Qt skaliert. Es liegt wahrscheinlich an der Art und Weise, wie ich die Größeneinstellung vorgenommen habe:

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());
}

Diese Größe wird nicht von Qt skaliert. Dasselbe passiert mit den Mausereigniskoordinaten.

Meine Frage: Gibt es eine Möglichkeit, um zu wissen, auf welche Größe die Skalierung durchgeführt wird?resizeGL() richtig? Oder wie gehe ich mit dem Problem richtig um?

Update / Lösung mit Skalierung von Hand: Dank der Antwort von @AlexanderVX habe ich die Skalierungslösung gefunden. Zuerst muss ich einige Referenzwerte für DPI in X- und Y-Dimensionen kennen. Daraufhin berechne ich die Skalierungskoordinaten und übergebe sie an mein WidgetQtOSGWidget. Also, der Code desmain() muss enthalten:

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.

Wenn ich dann auf die Größenfunktionen verweise, die an OpenSceneGraph (OpenGL) -Inhalte übergeben werden mussten, muss ich eine Skalierung durchführen,

// 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);

Endgültiges Update: Da die Zielplattform meiner Anwendung Windows 7-10 ist, ist es viel sinnvoller, die vorgeschlagene Antwort von @AlexanderV (zweiter Teil) beizubehalten, d. h. @ zu verwendeSetProcessDPIAware() Funktion.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage