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) 的相关文章

  • PyQt:如何设置组合框项目可检查?

    为了将 GUI 小部件数量保持在最低限度 我需要找到一种方法来为用户提供下拉菜单项的选择 这些菜单项可用于过滤掉 listWidget 项中显示的内容 假设 listWidget 列出了 5 个不同类别的项目 Cat A Cat B Cat
  • 为什么拥有单独的投影矩阵但结合模型和视图矩阵会有好处?

    当您学习 3D 编程时 您会被告知用 3 个变换矩阵来思考是最简单的 模型矩阵 该矩阵对于每个模型都是独立的 它根据需要旋转和缩放对象 最后将其移动到 3D 世界中的最终位置 模型矩阵将模型坐标转换为世界坐标 视图矩阵 对于大量对象 如果不
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • Qt:如何连接到 SQLite?

    我安装了 SQLite3 解压到 c sqlite 创建了一个数据库 c sqlite mzsales 现在我试图在 QTableView 中显示其内容 QSqlDatabase db QSqlDatabase addDatabase QS
  • 将 gnuplot 嵌入现有 QtWidget 中

    我正在用 C 创建一个 伪 实时绘图应用程序 使用 gnuplot 作为绘图后端 我的要求之一是绘图必须位于现有窗口内 而不是有一个单独的绘图窗口 gnuplot 默认为 Gnuplot 有一个选项可以指定 Qt 小部件 ID 这似乎适合我
  • Qt:在多个布局中使用一个小部件

    我有一个 QTabBar 所有选项卡都应该有相同的小部件 layout1 gt addWidget w layout2 gt addWidget w 然而打电话addWidget第二次导致该小部件在第一个布局中消失 有没有办法使用一个小部件
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 从 Qt4 中的文本文件中逐字读取

    我想在 Qt4 中逐字读取一个文本文件 说实话我对它很陌生 我想在另一个文件中每行一个字写入 我可以在 C 中做到这一点 没有任何问题 但是当我尝试在 Qt4 中使用 ifstream 和 ofstream 时 我遇到了错误 这是我的 Qt
  • 如何在 QtQuick 2 中对 QML TableView 进行排序?

    我想使用 Qt 5 1 实现具有自定义角色的可排序 TableView 但我不知道当用户单击标题时该怎么做才能对其进行排序 在我的 Qt pro 文件中 我添加了 android ios blackberry qtHaveModule wi
  • 在高 dpi Windows 平台上自动重新缩放应用程序?

    我正在编写一个需要在高 dpi Windows 192dpi 而不是 96dpi 上运行的 Qt 应用程序 不幸的是 Qt 框架尚不支持高 dpi 至少在 Windows 上 因此我的应用程序及其所有元素看起来只有应有尺寸的一半 有没有办法
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • 如何向同一个 QMenu 添加多个 QAction?

    我正在尝试实现 Qt 菜单自定义 并且我提供了一个功能来添加相同的功能QAction在同一个人民币上下文菜单中多次 但是当我尝试这样做时 myMenu gt addAction myAction myMenu gt addAction my
  • Mac 上的 Qt — 如何访问帮助菜单中的“搜索”

    我正在将我的 Qt 应用程序移植到 Mac OS X 在 Windows Linux 上 我使用 QLineEdit 在帮助菜单中提供搜索功能 In Mac OS X I saw something like this is built i
  • 如何仅剪切剪切平面的交集(而不是并集)?

    在 OpenGL JOGL 中 当使用多个剪切平面时 似乎会应用所有剪切平面的并集 我想要的是路口要应用的所有剪裁平面 这可能吗 请参阅下面的简化二维示例 Edit An example of clipping by vertex shad
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • 是否可以在 Qt Creator 中将 Qt 样式表与升级的小部件一起使用?

    我正在尝试使用 Qt 样式表对标准小部件进行一些重大的重新设计 因此 在为不同的小部件手动完成大部分工作之后 objectName选择器 我决定以某种方式对类似的小部件进行分组 例如我有多个QFrames其作用类似于内部表单中的标题 我希望
  • 使用 JOGL 和 Android OpenGL 编写可移植 Java 应用程序

    我计划编写一款可以在 PC 和 Android 上运行的 Java 3D 游戏 不幸的是 这两个平台似乎没有通用的 OpenGL API API 是否有显着差异 有没有办法在两个版本中使用相同的 3D 代码 这是不是一个好主意 Androi
  • 为什么 QGraphicsWidget 的选择边框在 QGraphicsScene 中不可见?

    我已经通过一个小部件添加到图形场景 QGraphicSscene QGraphicsProxyWidget 问题是 当我选择该项目时 它被选中 但选择边框不可见 这是代码 QDial dial new QDial Widget dial g
  • 如何访问Loader的sourceComponent中的QML对象?

    我可能需要读取或写入的一些属性Loader s sourceComponent来自一些外部函数 访问该房产的方式是什么x里面的对象的Loader s sourceComponent import QtQuick 2 0 Item width
  • 如何将 WPF 大小转换为物理像素?

    将 WPF 与分辨率无关 宽度和高度转换为物理屏幕像素的最佳方法是什么 我正在 WinForms 表单中显示 WPF 内容 通过 ElementHost 并尝试制定一些大小调整逻辑 当操作系统以默认 96 dpi 运行时 我可以正常工作 但

随机推荐

  • 如何在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 函数有以