2016-05-18 41 views
3

OpenGLラッパーライブラリ(OpenSceneGraph)を統合したQOpenGLWidgetを使用する最小限のアプリケーションがあります。私は使用しているようにOpenGLコンテンツを扱う際に、高DPI画面のQt5.6サポートを正しく使う方法を見つけようとしています。Qt5.6:高DPIサポートとOpenGL(OpenSceneGraph)

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

QtOSGWidgetはOpenSceneGraphのコンテンツにQOpenGLWidgetから派生されています:私は私の簡単なシーンをレンダリングするためにosgViewer::GraphicsWindowEmbeddedを使用

main()機能は、次のコードを持っています。

OSGをQtとマージするには、*GL()メソッドをpaintGL(),resizeGL()initializeGL()のように再定義します。私はすなわち、*GL()の各方法が含まれている必要がありますどのようにQtのドキュメントに従ってください。:

  • paintGL()必ずビューアが
  • resizeGL()は、グラフィックウィンドウを(一緒にカメラとビューポートで)適切にリサイズされているか確認します更新されます。
  • initializeGL()は、OpenGLの状態が初期化されていることを確認します。
  • Iも再定義されたQtのマウスイベントOSG

をイベントを渡すように、私は、通常の解像度の画面上で、またはQApplication::setAttribute(Qt::AA_DisableHighDpiScaling);と私の例を実行すると、それが必要のように、シーンが見えます:

cylinder example - high DPI support is off

また、カメラビューを操作すると、マウス座標が正しく取得されます。

私は上の高DPIのオプションを設定するときしかし、これは私が得るものです:

high DPI is on

イベントも同様にスケーリングされ、正しくOpenSceneGraphのイベントハンドラに渡されていないために、マウスの座標。

ご覧のとおり、グラフィックスウィンドウのサイズはQtでスケーリングされません。これはおそらく私がサイジングをどのようにセットアップするかの理由によるものです。

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

サイジングはQtでスケールされていません。マウスイベントの座標にも同じことが起こります。

私の質問:resizeGL()を正しく行うために、どのサイズのスケーリングが行われるかを知る方法はありますか?あるいは、問題に対処する正しい方法は何ですか?

@AlexanderVXの回答のおかげで、手動でスケーリングを使用した更新/解決:スケーリングの解決策を理解しました。まず、XとYの次元でDPIのいくつかの基準値を知る必要があります。次に、それに基づいてスケーリング座標を計算し、私のウィジェットQtOSGWidgetに渡します。だから、main()のコードが含まれています

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. 

をその後、私はOpenSceneGraph(OpenGLの)コンテンツに渡されるために必要なサイジング機能を参照するたびに、私は例えば、スケーリングを行う必要がある。

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

最終更新:私のアプリケーションのターゲットプラットフォームは、Windows 7から10であることから、それはSetProcessDPIAware()機能を使用するために、すなわち、@AlexanderVの提案答(第二部)に固執するより多くの意味があります。

+0

ウィンドウのサイズを変更するときにresizeメソッドが呼び出されますか? – KimKulling

+0

はい、私はそれを確認しました。毎回自動的に呼び出されます。 – vicrucann

答えて

2

どのようなサイズスケーリングはそう正しくresizeGL()を行うには を実行することになるために知る方法はありますか?

まず、モニター検出:

 // relative to widget 
     int screenNum = QApplication::desktop()->screenNumber(pWidget); 

または多分

 // relative to global screen position 
     int screenNum = QApplication::desktop()->screenNumber(pWidget->topLeft()); 

をし、それがQScreenに私たちにポインタを与える:

 QScreen* pScreen = QApplication::desktop()->screen(screenNum); 

あなたは多くの画面を読み取ることができます"phインチあたりのピクセル数が判断する私たちができるようになりインチあたりのドットysical」:

 qreal pxPerInch = pScreen->physicalDotsPerInch(); 

はあなたがプログラムで描画コードを拡張することができるようになります1インチあたりのピクセルを持ちます。 「標準」の密度をどれだけ検出し、物理デバイスで検出された密度に比例して拡大縮小します。もちろん、そのアプローチは正確なグラフィックスに適しています。ただし、physicalDotPerInch()devicePixelRatio()の両方に注意してください。

 qreal scaleFactor = pScreen->physicalDotsPerInch()/normalPxPerInch; 

や問題に対処するための正しい方法は何ですか?

しかし、ウィジェットと通常のGUI描画では、Qt /システムにUI全体を拡大させる方が簡単です。 Qtドキュメント:High DPI Displays

OS少なくともVistaまたはそれ以上で、Windowsおよび高DPIのためのQtのチューニングが複雑に聞こえる場合は、私が取ると、Qtはログに文句を言うものの、それは、私を助けショートカットがあります:。"SetProcessDpiAwareness failed: "COM error 0xffffffff80070005 (Unknown error 0x0ffffffff80070005)" は」私はからこの関数を呼び出しますSetProcessDPIAware()の前にmain()と表示されていますが、モニタの密度に関係なくすべてのUIが同じように見えますが、Qt 5.5でも使用しています。SetProcessDpiAwareness()関数もあります。Windows Vistaでは利用できるのでSetProcessDPIAwareを使用します。SetProcessDpiAwareness Windows 8.1以降でのみ利用可能であるため、潜在的なクライアントシステムに依存する可能性があります。

「ショートカット」アプローチ:

int main(int argc, char** argv) 
{ 
    // DPI support is on 
    // QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 

    // on Windows? 
    ::SetProcessDPIAware(); 
    // MSDN suggests not to use SetProcessDPIAware() as it is obsolete and may not be available. 
    // But it works with widgets. 

    QApplication app(argc, argv); 
    QMainWindow window; 

    // QOpenGLWidget with OpenSceneGraph content 
    QtOSGWidget* widget = new QtOSGWidget(); 

    window.setCentralWidget(widget); 
    window.show(); 
    return app.exec(); 
} 
+0

ありがとうございました。私は最初のアプローチを試みています。質問:どのように '正常な密度' normalPxPerInch'を検出するためのアイデアですか? – vicrucann

+0

「正常」と考えられるシステム上でコードを実行してください。 physicalDotsPerInchが返すものを見てみましょう。 – AlexanderVX

+0

もう一度ありがとうございます。私は最初のアプローチ(スケーリング)に行くと思います。私の簡単な例では、XとYの両方の寸法のスケーリングを計算しなければなりませんでした。私は 'QApplication :: desktop() - > physicalDpiX()'と 'QApplication :: desktop() - > physicalDpiY()'を使いました。あなたの答えは私がそれを理解するのを助けました。 – vicrucann

関連する問題