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

2023-11-26

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

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

The QtOSGWidget源自QOpenGLWidget与 OpenSceneGraph 内容:我使用osgViewer::GraphicsWindowEmbedded渲染我的简单场景。

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

  • paintGL()确保查看器已更新
  • resizeGL()确保图形窗口的大小正确调整(连同相机和视口);
  • initializeGL()确保 OpenGL 状态已初始化。
  • 我还重新定义了 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 的回答,我找到了扩展解决方案。首先,我需要知道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()功能。


有没有办法知道缩放将执行到什么大小 要做的事resizeGL()正确吗?

首先,检测显示器:

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

or maybe

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

这给了我们指向QScreen:

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

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

        qreal pxPerInch = pScreen->physicalDotsPerInch();

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

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

或者说处理问题的正确方法是什么?

然而,通过小部件和普通的 GUI 绘图,通常更容易让 Qt/系统缩放整个 UI。 Qt 文档:高 DPI 显示器.

如果操作系统 Windows 至少为 Vista 或更高版本,并且调整 Qt 以实现高 DPI 听起来很复杂,那么我采用了一个快捷方式,它对我有帮助,尽管 Qt 在日志中抱怨:"SetProcessDpiAwareness failed: "COM error 0xffffffff80070005 (Unknown error 0x0ffffffff80070005)"“。我将此函数称为main()在事件循环之前:设置进程DPIAware()然后,无论显示器密度是多少,所有用户界面看起来都一样。不过,我将它与 Qt 5.5 一起使用。还有设置ProcessDpiAwareness()功能, 探索.我用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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt5.6:高DPI支持和OpenGL(OpenSceneGraph) 的相关文章

  • Qt5和QML:如何使用WebEngine Quick Nano浏览器自动输入用户名和密码

    我正在使用编写一个小应用程序Qt and QML使用 Qt 文档中的示例WebEngine Quick Nano 浏览器 https doc snapshots qt io qt5 5 9 qtwebengine webengine qui
  • 如何使用 Qt DOM 通过此语法获取 xml 属性

    我正在使用 Qt DOM XML 解析器 并且遇到了如下属性定义的问题
  • Shader的功能参数表现

    我试图了解如何在着色器语言中实现传递参数 我读过几篇文章和文档 但仍然有一些疑问 特别是我试图理解与C 函数调用 特别强调性能 之间略有差异HLSL Cg and GLSL但我猜下划线的实现非常相似 到目前为止我所理解的 除非另有说明 函数
  • OpenGL 与 OpenCL,选择哪个以及为什么?

    哪些功能使 OpenCL 能够独特地选择 OpenGL 和 GLSL 进行计算 尽管有与图形相关的术语和不实用的数据类型 OpenGL 是否有任何真正的警告 例如 可以通过使用其他纹理将 a 渲染到纹理来完成并行函数评估 减少操作可以通过迭
  • 如何让小部件在上下文菜单出现时接收鼠标释放事件

    在Ubuntu20 04上 当上下文菜单出现时 我无法让小部件接收鼠标释放事件 而Windows可以接收 我的pyqt版本是5 15 2 我考虑过手动发送鼠标释放事件 但我不知道当上下文菜单出现时哪些系统会收到鼠标释放事件 这样做可能会导致
  • 获取 QListView 中所有可见项目的简单方法

    我正在尝试使用 Qt Framework 开发一个图像库应用程序 应用程序从所选文件夹加载所有图像 并使用 QListView 控件显示这些图像 但现在我想通过仅加载用户可见的图像来减少内存消耗 由于没有直接函数来获取视图中的所有可见项目
  • 清除pyqt中布局中的所有小部件

    有没有办法清除 删除 布局中的所有小部件 self plot layout QtGui QGridLayout self plot layout setGeometry QtCore QRect 200 200 200 200 self r
  • 完全彻底卸载QT Creator

    问题 如何从 Linux 机器上卸载 QT Creator 我的 Debian Jessie 机器上的安装已损坏 我尝试过重新安装 修复等 但没有成功 建议我完全卸载 获取最新版本并重新安装 问题是我不确定如何执行此操作 每次我尝试时 QT
  • 进行亚像素平移时,2D 纹理会扭曲

    我想知道一个理论推理为什么这是可能的 几何体的平移与纹理映射有何关系 我只能在进行子像素平移时注意到这种效果 如果通过整个像素平移 纹理看起来很好 我正在使用正交投影 GL CLAMP TO EDGE GL NEAREST 片段着色器是hi
  • glTranslatef 不在 glBegin .. glEnd 中工作

    我正在尝试并排绘制不同颜色的两个方块 我的问题是我无法让 glTranslatef 将第二个方块向右移动 第二个方块只是绘制在第一个方块上 void display void glClear GL COLOR BUFFER BIT glMa
  • 如何在 R 中导入并绘制三角形网格?

    我想在 R 中绘制我的模型输出 它是格式为的三角形网格 x1 y1 z1 x2 y2 z2 x3 y3 z3 value 每行代表一个三角形 我想用以下方法绘制这些三角形value作为规模 mymesh lt structure c 0 9
  • 覆盖 QWebView 中的页面回复

    我试图在 Qt 的 QWebView 中拦截页面 表单请求 并在某些情况下使用替代内容进行响应 QNetworkReply ngcBrowser createRequest Operation operation const QNetwor
  • OpenGL 新手: glutMouseFunc

    我试图在单击鼠标后更改球体位置 但在使用 glutMouseFunc 中的 x 和 y 时它不起作用 以下是代码 include stdafx h include
  • 连接到 QNetworkReply::error 信号

    我正在使用 Qt5 的新连接语法 QNetworkReply 有一个名为error http qt project org doc qt 5 0 qtnetwork qnetworkreply html error 2还有一个函数叫做err
  • 了解 Qt3D 创建的网格

    我创建了一个 Qt3D 网格 如下所示 Qt3DCore QEntity newEntity new Qt3DCore QEntity Qt3DExtras QConeMesh mesh new Qt3DExtras QConeMesh m
  • PyQt4 信号和槽

    我正在使用 PyQt4 编写我的第一个 Python 应用程序 我有一个 MainWindow 和一个 Dialog 类 它是 MainWindow 类的一部分 self loginDialog LoginDialog 我使用插槽和信号 这
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态
  • 无法运行 Qt 应用程序:找不到版本“Qt_5”

    我运行 Ubuntu 16 04 LTS 我的问题是我无法运行可以编译的 Qt5 应用程序 这是我尝试运行它时得到的结果 home user Desktop sconfig dist Release GNU Linux SCongif us
  • QFileSystemModel setRootPath

    我正在尝试创建一个 Qt 应用程序来显示文件夹 Mac OS 中的 Users 文件夹 的内容 这是代码 QFileSystemModel dirModel new QFileSystemModel dirModel gt setRootP
  • sRGB 纹理。它是否正确?

    我最近阅读了一些有关 sRGB 格式以及它们如何允许硬件自动对典型显示器执行色彩校正的文章 作为我阅读的一部分 我发现您可以使用普通纹理和返回结果上的 pow 函数来模拟此步骤 无论如何 我想问两个问题 因为我以前从未使用过此功能 首先 有

随机推荐

  • 如何在Spring LDAP中添加LDAP缓存?

    我想在本地缓存 LDAP 用户数据以允许更快的查询 Spring LDAP 提供这样的功能吗 我怎样才能做到这一点 我使用 Spring Security 3 1 和 Spring LDAP 1 3 1 进行身份验证和授权 如果存在使用内置
  • 无法在同一文件中使用模块和主程序进行编译

    我正在尝试使用与主程序位于同一文件中的模块 但是 我无法让它工作 Fortran 是否允许模块与主程序包含在同一文件中 还是必须位于单独的文件中 这是我的代码的简单版本 main program use my module call my
  • ggplot2:如何在单个图中组合直方图、地毯图和逻辑回归预测

    我正在尝试绘制逻辑回归的组合图作为函数逻辑直方图但我想用ggplot2 审美原因 问题是只有一个直方图应该具有scale y reverse 有什么方法可以在单个图中指定这一点 请参见下面的代码 或者通过使用可以传递到前一个图的坐标来重叠两
  • 如何使用 Python 在 OpenCV 中裁剪图像

    如何使用 OpenCV 裁剪图像 就像我之前在 PIL 中所做的那样 PIL 上的工作示例 im Image open 0 png convert L im im crop 1 1 98 33 im save 0 png 但是我如何在 Op
  • 获取java类的编译时间戳

    是否可以可靠地确定本地运行的 Java 应用程序以及作为小程序和 或 JNLP Web 应用程序运行的给定类的编译时间戳 根据 Java 虚拟机规范 类文件格式不需要任何类型的时间戳 因此您最好检查包含该类的 Class 或 Jar 文件的
  • 如何修剪前导和尾随空白?

    我在处理 data frame 中的前导和尾随空格时遇到一些问题 例如 我查看一个特定的row in a data frame基于某种条件 gt myDummy myDummy country c Austria c 1 2 3 7 19
  • 使用 xUnit 处理 netstandard1.6

    我希望使用 netstandard1 6 库的测试框架 我尝试关注并编辑xUnit net 入门 NET Core ASP NET Core 没有成功 按照 xUnit 的教程 使用 VS 2015 Update 3 RTM 上的 dotn
  • 使用spel访问spring注释中的静态变量

    我在注释中有一个值 我想为其分配一个静态变量 我尝试过这样的事情 Cacheable value com test App VALUE public List someCachableMethod 尝试此操作后 仍然出现相同的异常 找不到字
  • Android Facebook 意图

    我正在使用此代码在 Facebook 上发布 但它不适用于官方 Facebook 应用程序 因为它尝试作为链接发送 有没有办法解决 Intent s new Intent android content Intent ACTION SEND
  • Android:添加一个简单的片段

    我对 Android 应用程序还很陌生 所以我希望能在这里找到一些帮助 我已经在这里搜索了我的问题并找到了一些东西 但这不起作用 我想将 Fragment 添加到 FrameLayout 但它不起作用 我的目标是创建一个始终存在的框架 框架
  • 在 ggplot x 轴上显示所有日期值 - R

    在下面的小数据集中 我想在 x 轴上绘制日期值 我希望标记数据框中存在的所有日期刻度 目前它只标记 3 个随机刻度 我可以将该列更改为一个因子 但将其作为日期意味着 x 轴根据点之间的时间间隔进行间隔 到目前为止 我能找到的唯一答案是想要每
  • Python正则表达式匹配字符串末尾的标点符号

    我需要在Python中匹配一个句子是否以大写开头并以 结尾 EDIT它必须有 only at end 但允许在句子中使用其他标点符号 import re s This sentence is correct This sentence is
  • python 有 soundex 函数吗?

    python 是否有 soundex 函数 如果没有 你将如何编写 soundex 代码 Soundex Code Letters 1 B F P V 2 C G J K Q S X Z 3 D T 4 L 5 M N 6 R SKIP A
  • Objective C - 静态和全局变量?

    在名为 Ad 的类的 m 文件中 我有 3 个静态字符串 static NSString AdStateDisabled disable static NSString AdStateExpired expired static NSStr
  • 构建oozie:未知主机repository.codehaus.org

    我正在尝试构建从此处下载的 Oozie 4 2 0 http ftp cixug es apache oozie 4 2 0 oozie 4 2 0 tar gz 启动构建后 bin mkdistro sh DskipTests 我收到此错
  • 适用于作业服务器的 Amazon Auto Scaling API

    我已经阅读了几乎整个文档 甚至超出了 AWS AS API 的范围 以了解所有 AS 内容 然而 我仍然想知道 尚未实际使用 API 因为我想先从某人那里找到这一点 我的场景是否适用于 AS 假设我在一个 AS 组内设置了一堆工作服务器 每
  • 如何抑制 Python 日志记录模块中的换行符。 [复制]

    这个问题在这里已经有答案了 我想在执行 log info msg 操作时取消换行符 当我们 打印 它时 print msg 所以我需要像 coma 这样的东西来记录 我播下这个问题在 Python 日志记录模块中禁止换行但有人可以给我参考或
  • 使用 React 从 Babel 迁移到 SWC

    TL DR 如何翻译这样的节点脚本 test NODE ENV test riteway r babel register src test js tap nirvana to use SWC而不是巴别塔 Context 我们最近升级了 N
  • 如何检查另一个窗口中是否有打开的 URL?

    这是我上一个问题的后续如果窗口尚不存在 则打开一个窗口本质上 我现在保留一个页面已打开的所有窗口引用的列表 并且仅允许它们尚未打开时打开 然后一个潜在的问题引起了我的注意 用户当然有可能关闭原始窗口 然后再次打开它 从而丢失窗口引用列表 是
  • Qt5.6:高DPI支持和OpenGL(OpenSceneGraph)

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