探索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" …...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
