首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Qt5.6:新闻部的高度支持和OpenGL (OpenSceneGraph)

Qt5.6:新闻部的高度支持和OpenGL (OpenSceneGraph)
EN

Stack Overflow用户
提问于 2016-05-18 15:24:57
回答 1查看 3.9K关注 0票数 6

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

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

代码语言:javascript
运行
复制
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()确保适当调整图形窗口的大小(连同摄像机和视口);
  • initializeGL()确保初始化了OpenGL状态。
  • 我还重新定义了Qt鼠标事件,以便将事件传递给OSG。

当我在普通分辨率屏幕上或在QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);上运行我的示例时,场景看起来应该:

此外,当我操作相机视图时,鼠标坐标将被正确捕获。

然而,当我设置高DPI选项时,我得到的是:

事件的鼠标坐标也是缩放的,没有正确传递给OpenSceneGraph的事件处理程序。

正如您所看到的,图形窗口的大小不是由Qt缩放的。这可能是因为我设置调整大小的方式:

代码语言:javascript
运行
复制
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()的代码必须包含:

代码语言:javascript
运行
复制
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)内容的大小调整函数时,我就必须进行缩放,例如:

代码语言:javascript
运行
复制
// 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);

最终更新:由于我的应用程序的目标平台是Windows7-10,所以坚持使用@AlexanderV (第二部分)的建议答案更有意义,即使用SetProcessDPIAware()函数。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-18 16:13:14

是否有一种方法可以知道将执行多大的缩放,以便正确地执行resizeGL()

首先,检测监视器:

代码语言:javascript
运行
复制
        // relative to widget
        int screenNum = QApplication::desktop()->screenNumber(pWidget);

或者也许

代码语言:javascript
运行
复制
        // relative to global screen position
        int screenNum = QApplication::desktop()->screenNumber(pWidget->topLeft());

这给了我们指向QScreen的指针

代码语言:javascript
运行
复制
        QScreen* pScreen = QApplication::desktop()->screen(screenNum);

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

代码语言:javascript
运行
复制
        qreal pxPerInch = pScreen->physicalDotsPerInch();

拥有每英寸的像素,您将能够以编程方式缩放绘图代码。检测出多少是“正常”密度,然后与物理设备上检测到的密度成比例地进行缩放。当然,这种方法更适合于精确的图形。不过,要注意physicalDotPerInch()devicePixelRatio()

代码语言:javascript
运行
复制
        qreal scaleFactor = pScreen->physicalDotsPerInch() / normalPxPerInch;

或者什么是正确的方法来处理这个问题?

然而,使用小部件和普通GUI绘图,让Qt / system扩展整个UI通常更容易。Qt文档:高点阵显示器

如果操作系统至少是Vista或更高版本,并为高DPI调整Qt听起来很复杂,那么我采取了一种快捷方式,它帮助了我,尽管Qt在日志中抱怨:"SetProcessDpiAwareness failed: "COM error 0xffffffff80070005 (Unknown error 0x0ffffffff80070005)"“。我在事件循环之前从main()调用这个函数:SetProcessDPIAware(),然后不管监视器密度如何,所有UI看起来都很相似。不过,我在QT5.5中使用它。还有SetProcessDpiAwareness()函数,探索。我之所以使用SetProcessDPIAware,是因为它可以从Windows中获得,而SetProcessDpiAwareness只在Windows8.1之后才可用。因此,这个决定可能取决于潜在的客户系统。

一种“捷径”方法:

代码语言:javascript
运行
复制
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();
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37303941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档