gpt4 book ai didi

Qt5.6:高DPI支持和OpenGL(OpenSceneGraph)

转载 作者:行者123 更新时间:2023-12-01 17:01:22 27 4
gpt4 key购买 nike

我有一个最小的应用程序,它使用集成了 OpenGL 包装器库 (OpenSceneGraph) 的 QOpenGLWidget。我试图弄清楚在处理我使用的 OpenGL 内容时如何正确使用 Qt5.6 对高 DPI 屏幕的支持。

我的 main() 函数具有以下代码:

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 来渲染我的简单场景。

为了将 OSG 与 Qt 合并,我重新定义了 *GL() 方法:paintGL()resizeGL()initializeGL()。我遵循 Qt 文档了解每个 *GL() 方法应包含的内容,即:

  • paintGL() 确保查看器已更新
  • resizeGL() 确保正确调整图形窗口的大小(连同相机和视口(viewport));
  • initializeGL() 确保 OpenGL 状态已初始化。
  • 我还重新定义了 Qt 鼠标事件,以便将事件传递给 OSG

当我在正常分辨率屏幕上运行示例时,或者使用 QApplication::setAttribute(Qt::AA_DisableHighDpiScaling); 运行示例时,场景看起来应该是这样的:

cylinder example - high DPI support is off

此外,当我操纵相机 View 时,可以正确捕获鼠标坐标。

但是,当我设置高 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的回答,我找到了缩放解决方案。首先,我需要知道DPI在X和Y维度上的一些引用值。然后,我根据该坐标计算缩放坐标,并将它们传递给我的小部件 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,因此坚持@AlexanderV(第二部分)建议的答案更有意义,即使用 SetProcessDPIAware()函数。

最佳答案

Is there a way to know to what size the scaling will be performed so that to do resizeGL() correctly?

首先,检测显示器:

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

从中您可以读取许多屏幕特征,包括“每英寸物理点”,这使我们能够判断每英寸有多少像素:

        qreal pxPerInch = pScreen->physicalDotsPerInch();

有了每英寸像素,您将能够以编程方式缩放绘图代码。检测“正常”密度是多少,然后根据物理设备上检测到的密度按比例缩放。当然这种方法更适合精确的图形。请注意两者physicalDotPerInch()devicePixelRatio()不过。

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

Or what is the correct way to deal with the problem?

但是,使用小部件和正常的 GUI 绘图,通常更容易让 Qt/系统缩放整个 UI。 Qt 文档:High DPI Displays .

如果操作系统 Windows 至少为 Vista 或更高版本,并且调整 Qt 以实现高 DPI 听起来很复杂,那么我采用了一个快捷方式,它对我有帮助,尽管 Qt 在日志中提示:“SetProcessDpiAwareness failed:”COM error 0xffffffff80070005(未知错误0x0ffffffff80070005)”“。我在事件循环之前从 main() 调用此函数:SetProcessDPIAware(),然后无论显示器密度是多少,所有 UI 看起来都一样。不过,我将它与 Qt 5.5 一起使用。有还有 SetProcessDpiAwareness() 函数,探索。我使用 SetProcessDPIAware 因为它自 Windows Vista 起可用,但 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();
}

关于Qt5.6:高DPI支持和OpenGL(OpenSceneGraph),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37303941/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com