禁止指定ip访问网站百度网盘app下载安装
在处理屏幕显示和多显示器环境时,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 提供的信号与槽机制在多屏幕、多设备环境中具有重要的应用场景。通过这些信号,我们能够动态地响应屏幕的变化,例如分辨率变化、方向变化以及主屏幕的切换,确保应用在不同屏幕和显示环境下都能正常工作。