探索QScreen的信号与槽:动态响应屏幕变化
在处理屏幕显示和多显示器环境时,QScreen 提供了一些特有的信号,这些信号可以在屏幕的变化时通知应用程序,帮助我们动态地适配和响应显示设备的变化。今天,我们将深入探讨如何使用 QScreen 的信号与槽,并展示适用的使用场景。
QScreen信号概述
在 Qt6 中,QScreen 类提供了几个重要的信号,允许我们在屏幕的属性发生变化时进行响应。以下是 QScreen 中的一些关键信号:
1. geometryChanged(const QRect &geometry)
当屏幕的几何区域发生变化时(例如,屏幕的分辨率或位置发生变化),此信号会被发出。
2. availableGeometryChanged(const QRect &availableGeometry)
当屏幕的可用显示区域发生变化时发出信号。可用区域变化可能是由于任务栏的出现或屏幕分辨率的改变等因素引起的。
3. orientationChanged(Qt::ScreenOrientation orientation)
当屏幕的方向发生变化时发出信号。这对于处理屏幕旋转(如从竖屏到横屏)尤其有用。
4. primaryScreenChanged(QScreen *primaryScreen)
当系统的主屏幕发生变化时发出此信号。通常是由于用户调整显示设置,或者操作系统自动更改主屏幕的显示设备。
信号槽的基本使用
1. 监听屏幕几何区域的变化
如果你希望在屏幕的几何区域发生变化时更新界面布局或窗口位置,可以连接 geometryChanged 信号到一个槽。例如,当用户调整屏幕的分辨率时,我们可以重新计算窗口位置或大小,确保窗口显示在正确的位置。
screen_monitor.h
#ifndef SCREEN_MONITOR_H
#define SCREEN_MONITOR_H#include <QScreen>
#include <QDebug>
#include <QGuiApplication>class ScreenMonitor : public QObject
{Q_OBJECTpublic:ScreenMonitor(QScreen *screen){// 连接信号到槽connect(screen, &QScreen::geometryChanged, this, &ScreenMonitor::onGeometryChanged);qDebug() << "Wait for geometry changed ...";}private slots:void onGeometryChanged(const QRect &geometry){qDebug() << "Screen geometry changed : " << geometry;// 在这里可以处理几何区域变化后的逻辑}
};#endif // SCREEN_MONITOR_H
main.cpp
#include <QGuiApplication>
#include "screen_monitor.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);// 获取主屏幕QScreen *screen = QGuiApplication::primaryScreen();// 创建监视对象ScreenMonitor monitor(screen);return app.exec();
}
在这个示例中,我们创建了一个 ScreenMonitor 类,它将 QScreen 的 geometryChanged 信号连接到槽 onGeometryChanged。每当屏幕的几何区域发生变化时,系统将触发该槽,并输出新几何区域。
当屏幕分辨率发生变化时,会触发此信号。
Qt程序输出结果:
2. 监听可用区域变化
有时,我们不仅需要知道屏幕的几何区域,还需要关注屏幕的可用区域,比如当任务栏或其他系统界面元素出现或消失时(这里有待验证)。如果你正在开发一个多窗口的应用,监听 availableGeometryChanged 信号将非常有用。
在screen_monitor.h中增加AvailableGeometryMonitor类:
class AvailableGeometryMonitor : public QObject
{Q_OBJECTpublic:AvailableGeometryMonitor(QScreen *screen){// 连接信号到槽connect(screen, &QScreen::availableGeometryChanged, this, &AvailableGeometryMonitor::onAvailableGeometryChanged);qDebug() << "Wait for available geometry changed ...";}private slots:void onAvailableGeometryChanged(const QRect &availableGeometry){qDebug() << "Screen available geometry changed:" << availableGeometry;// 根据新的可用区域调整窗口大小或位置}
};
修改main.cpp为:
#include <QGuiApplication>
#include "screen_monitor.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);// 获取主屏幕QScreen *screen = QGuiApplication::primaryScreen();// 创建监视对象ScreenMonitor monitor1(screen);AvailableGeometryMonitor monitor2(screen);return app.exec();
}
在这个例子中,我们创建了一个 AvailableGeometryMonitor 类,当屏幕的可用显示区域发生变化时,系统会触发 onAvailableGeometryChanged 槽函数。在这种情况下,我们可以根据新的可用区域调整应用的布局或窗口大小。
验证:
当屏幕分辨率发生变化时,会触发以上2个信号,运行后打印如下:
当前使用的Qt版本为6.7,操作系统为Win10,测试:
- 解除任务栏锁定,拉伸任务栏高度
- 调整为自动隐藏
- 调整任务栏在桌面上的位置(顶部、底部、左右侧)
均不会被以上2个信号(geometryChanged、availableGeometryChanged)捕获。
由此可见,可用的几何区域只会被分辨率影响。系统菜单栏的位置和高度不会影响available geometry属性。此结论有待进一步验证,后续换个环境继续测试一下。
继续在 Qt6.8 + Win11(24H2)上验证:
1. 修改缩放比例
不会触发geometryChanged、availableGeometryChanged信号。
2. 修改分辨率
将分辨率由2560*1600改为2560*1440
依旧不会触发geometryChanged、availableGeometryChanged信号。
3. 修改任务栏高度或位置
Win11默认无法修改任务栏高度和位置,这里编辑注册表(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StuckRects3),将图中圈出的位置,由03改为01,目的是将任务栏置顶:
修改完毕后,重启windows资源管理器:
结果:
修改注册表无效,重启后系统重置回来了。Windows11不希望用户去改变任务栏的位置和大小。
既然信号无法被触发,测试一下属性是否被修改。在main.cpp代码中添加打印:
#include <QGuiApplication>
#include "screen_monitor.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);// 获取主屏幕QScreen *screen = QGuiApplication::primaryScreen();// 创建监视对象ScreenMonitor monitor1(screen);AvailableGeometryMonitor monitor2(screen);qDebug() << "geometry: " << screen->geometry();qDebug() << "availableGeometry: " << screen->availableGeometry();return app.exec();
}
修改分辨率后,重新启动程序,发现属性还是被更改了,只是无法通过信号槽进行监控。
目前的结论:
使用Qt6,在Win10上,分辨率的变化会触发geometry改变信号,而修改系统菜单栏的位置和高度不会触发geometry改变信号。在Win11上,分辨率变化无法触发geometry改变信号,但是通过打印来看,属性值已被更改。
3. 监听屏幕方向变化
当屏幕方向发生变化时(例如,设备旋转),orientationChanged 信号将被触发。对于需要响应屏幕方向变化的应用(如支持竖屏和横屏切换的应用),使用这个信号是非常重要的。
在screen_monitor.h中增加AvailableGeometryMonitor类:
class OrientationMonitor : public QObject
{Q_OBJECTpublic:OrientationMonitor(QScreen *screen){// 连接信号到槽connect(screen, &QScreen::orientationChanged, this, &OrientationMonitor::onOrientationChanged);qDebug() << "Wait for orientation changed ...";}private slots:void onOrientationChanged(Qt::ScreenOrientation orientation){qDebug() << "Screen orientation changed:" << orientation;// 根据新的方向调整应用界面或行为}
};
将main.cpp修改为:
#include <QGuiApplication>
#include "screen_monitor.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);// 获取主屏幕QScreen *screen = QGuiApplication::primaryScreen();// 创建监视对象ScreenMonitor monitor1(screen);AvailableGeometryMonitor monitor2(screen);OrientationMonitor monitor3(screen);return app.exec();
}
在这个示例中,我们监控屏幕方向的变化,每当设备从竖屏切换到横屏或反之时,系统会触发 onOrientationChanged 信号。可以在这个槽中处理相应的界面调整逻辑。
Qt::ScreenOrientation(屏幕方向枚举) 说明:
- PrimaryOrientation 显示器的主方向
- PortraitOrientation 横向,显示宽度大于显示高度
- LandscapeOrientation 纵向,显示高度大于显示宽度,相对于横向顺时针旋转90度
- InvertedPortraitOrientation 横向翻转,相对于PortraitOrientation旋转180度
- InvertedLandscapeOrientation 纵向翻转,相对于LandscapeOrientation旋转180度
验证:
在Qt6.7 + Win10电脑上,将屏幕方向由横向改为纵向,会触发以上3个信号。而在Qt6.8 + Win11(24H2)电脑上,主屏幕本身是横屏的,从横屏切换到竖屏不会触发以上3个信号。在Windows上差异还是挺大的,旋转屏幕的场景更适用于移动端,目前没有验证。
4. 监听主屏幕变化
在某些情况下,应用程序需要知道系统的主屏幕是否发生变化。例如,当用户将主显示器从一个屏幕切换到另一个时,我们可能需要重新调整应用窗口的显示位置。primaryScreenChanged 信号就是为了处理这种情况。
在screen_monitor.h中增加PrimaryScreenMonitor类:
class PrimaryScreenMonitor : public QObject
{Q_OBJECTpublic:PrimaryScreenMonitor(){// 连接信号到槽connect(qApp, &QGuiApplication::primaryScreenChanged, this, &PrimaryScreenMonitor::onPrimaryScreenChanged);qDebug() << "Wait for primary screen changed ...";}private slots:void onPrimaryScreenChanged(QScreen *primaryScreen){qDebug() << "Primary screen changed to:" << primaryScreen->name();// 可以在这里根据新的主屏幕位置调整窗口}
};
修改main.cpp:
#include <QGuiApplication>
#include "screen_monitor.h"int main(int argc, char *argv[])
{QGuiApplication app(argc, argv);// 获取主屏幕QScreen *screen = QGuiApplication::primaryScreen();// 创建监视对象ScreenMonitor monitor1(screen);AvailableGeometryMonitor monitor2(screen);OrientationMonitor monitor3(screen);PrimaryScreenMonitor monitor4;return app.exec();
}
在这个示例中,我们使用了 QGuiApplication::primaryScreenChanged 信号来监听主屏幕的变化,每当系统主屏幕发生变化时,onPrimaryScreenChanged 槽将会被触发。你可以根据新的主屏幕位置调整窗口的显示。
使用场景
1. 多显示器支持
在多显示器环境下,监控屏幕几何变化和可用区域变化非常重要。可以根据不同显示器的几何变化调整应用窗口的位置和大小。例如,当用户将窗口从一个显示器拖动到另一个显示器时,应用可以自动适应新的屏幕几何。
2. 屏幕旋转
对于需要支持屏幕旋转(如平板设备或手机)的应用,监听屏幕方向变化至关重要。当屏幕方向发生变化时,应用可以自动调整布局,使其适应新的方向。
3. 响应主屏幕切换
如果应用需要支持多显示器系统中的主屏幕切换,可以通过 primaryScreenChanged 信号来获得通知,并在主屏幕变化时重新定位或调整窗口。
总结
QScreen 提供的信号与槽机制在多屏幕、多设备环境中具有重要的应用场景。通过这些信号,我们能够动态地响应屏幕的变化,例如分辨率变化、方向变化以及主屏幕的切换,确保应用在不同屏幕和显示环境下都能正常工作。
相关文章:

探索QScreen的信号与槽:动态响应屏幕变化
在处理屏幕显示和多显示器环境时,QScreen 提供了一些特有的信号,这些信号可以在屏幕的变化时通知应用程序,帮助我们动态地适配和响应显示设备的变化。今天,我们将深入探讨如何使用 QScreen 的信号与槽,并展示适用的使用…...

vLLM项目加入PyTorch生态系统,引领LLM推理新纪元
近日,vLLM项目宣布正式成为PyTorch生态系统的一部分,标志着该项目与PyTorch的合作进入了一个全新的阶段。本文将从以下几个方面进行介绍,特别提醒:安装方案在第四个部分,可选择性阅读。 vLLM项目概述 vLLM的成就与实际…...

索引-介绍结构语法
一.概述: 1.当给某个字段创建索引后,就会把字段生成二叉排序树进行查找,大大增加了查找效率,比不创建索引时用的全表扫描好得多。 2.二叉排序树:小的在左边,大的在右边(查找和存放都遵循这个原则)。 3.注…...

SpringBoot整合JDBC
讲到这里,基本上我们就可以使用SpringBoot来开发Web项目视图显示和业务逻辑代码,但是要做一个完成案例,我们还差一点点,就是怎么访问数据库,获取数据,接下来我们就看怎么用SpringBoot整合我们前面已经讲过的…...

XXE靶场
XXE-lab 靶场 靶场网址:http://172.16.0.87/ 第一步我们看到网站有登录框我们试着用 bp 去抓一下包 将抓到的包发到重放器中 然后我们构建palody <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/readconvert.base64-encode/resourceC:/flag/fla…...

Elasticsearch:使用 Open Crawler 和 semantic text 进行语义搜索
作者:来自 Elastic Jeff Vestal 了解如何使用开放爬虫与 semantic text 字段结合来轻松抓取网站并使其可进行语义搜索。 Elastic Open Crawler 演练 我们在这里要做什么? Elastic Open Crawler 是 Elastic 托管爬虫的后继者。 Semantic text 是 Elasti…...

Facebook的隐私保护政策:用户数据如何在平台上被管理?
在当今数字化世界,社交平台如何管理用户数据并保护隐私成为了一个热点话题。作为全球最大的社交网络,Facebook(现Meta)在数据隐私方面的政策备受关注。本文将简要介绍Facebook的隐私保护措施,以及用户数据如何在平台上…...
【ETCD】【源码阅读】深入解析 EtcdServer.applySnapshot方法
今天我们来一步步分析ETCD中applySnapshot函数 一、函数完整代码 函数的完整代码如下: func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) {if raft.IsEmptySnap(apply.snapshot) {return}applySnapshotInProgress.Inc()lg : s.Logger()lg.In…...

HBase是什么,HBase介绍
官方网站:Apache HBase – Apache HBase Home HBase是一个分布式的、面向列的NoSQL数据库,主要用于存储和处理海量数据。它起源于Google的BigTable论文,是Apache Hadoop项目的子项目。HBase设计用于高可靠性、高性能和可伸…...
【Rust自学】3.3. 数据类型:复合类型
3.3.0. 写在正文之前 欢迎来到Rust自学的第三章,一共有6个小节,分别是: 变量与可变性数据类型:标量类型数据类型:复合类型(本文)函数和注释控制流:if else控制流:循环 通过第二章…...

【C++】小乐乐求和问题的高效求解与算法对比分析
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯问题描述与数学模型1.1 题目概述1.2 输入输出要求1.3 数学建模 💯方法一:朴素循环求和法2.1 实现原理2.2 分析与问题2.3 改进方案2.4 性能瓶颈与结论…...

configure错误:“C compiler cannot create executables“
执行./configure命令出现如下奇怪的错误,百思不得姐: ./configure命令的日志文件为config.log,发生错误时,该文件的内容: This file contains any messages produced by compilers while running configure, to aid d…...

PAT乙级 锤子剪刀布 巩固巩固map的使用
主要是想借这题巩固巩固c map的使用方法。 大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。 输…...

Webpack学习笔记(1)
1.为什么使用webpack? webpack不仅可以打包js代码,并且那个且支持es模块化和commonjs,支持其他静态资源打包,如图片、字体。。。 2.如何解决作用域问题? 作用域问题:例如loadsh等库,会绑定window对象,会…...

使用xpath规则进行提取数据并存储
下载lxml !pip install lxmlimport requests headers{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36" } url"https://movie.douban.com/chart" respon…...

【物联网技术与应用】实验3:七彩LED灯闪烁
实验3 七彩LED灯闪烁 【实验介绍】 七彩LED灯上电后,7色动闪光LED模块可自动闪烁内置颜色。它可以用来制作相当吸引人的灯光效果。 【实验组件】 ● Arduino Uno主板* 1 ● USB数据线* 1 ● 7彩LED模块*1 ● 面包板*1 ● 9V方型电池*1 ● 跳线若干 【实验原…...

素数回文数的个数
素数回文数的个数 C语言代码C 代码Java代码Python代码 💐The Begin💐点点关注,收藏不迷路💐 求11到n之间(包括n),既是素数又是回文数的整数有多少个。 输入 一个大于11小于1000的整数n。 输出…...
车辆重识别代码笔记12.18
1、实例归一化(Instance Normalization)和批量归一化(Batch Normalization) 实例归一化(Instance Normalization): 计算步骤: 对于每个输入样本,在每个通道上分别计算均…...

selenium 在已打开浏览器上继续调试
关闭浏览器,终端执行如下指令,--user-data-dir换成自己的User Data路径 chrome.exe --remote-debugging-port9222 --user-data-dir"C:\Users\xxx\AppData\Local\Google\Chrome\User Data" 会打开浏览器,打开百度,如下状…...

Sentry日志管理thinkphp8 tp8 sentry9 sentry8 php8.x配置步骤, tp8自定义异常处理类使用方法
tp8的默认使用的就是composer来管理第三方包, 所以直接使用 composer 来安装 sentry9 即可. 同时tp8和tp5的配置方式不太一样, 这里我们直接使用自定义异常类来处理Sentry的异常. 1. 安装 sentry9 包 # 安装 sentry9 包 composer require "tekintian/sentry9-php" …...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...