QT多屏显示程序

多屏显示的原理其实很好理解,就拿横向扩展来说:
计算机把桌面的 宽度扩展成了 w1(屏幕1的宽度) + w2(屏幕2的宽度) 。
当一个窗口的起始横坐标 > w1,则 他就被显示在第二个屏幕上了。

drm设备可以多用户同时打开,FB获取的用户态虚拟内存地址映射到内核态物理内存地址也是不同的

多屏虚拟成一个桌面,QScreen Class。qtbase/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp

QT可用的平台插件有:xcb、eglfs、linuxfb、minimal、minimalegl、offscreen、vnc、wayland-egl、wayland、wayland-xcomposite-egl、wayland-xcomposite-glx、webgl等

 

qt的说明文档中用一张图阐述了这个情况:
 

在这里插入图片描述


QApplication 提供了一个获得virtual desktop的方法:
QDesktopWidget *desktop = QApplication::desktop();
返回的 QDesktopWidget 存储着当前桌面的信息。

注意 ,这个函数必须在创建了 QApplication 对象之后才能使用, 否则会出错。具体原因,要问qt。

这个desktop有几个很有用的函数,用来获取当前的屏幕状态和分辨率
1) int desktop->primaryScreen()
获取主屏幕的索引序号,(windows开始菜单所在的屏幕为主屏幕), 每个副屏幕序号+1

2) int desktop->screenCount()
获取当前屏幕个数

3) QRect desktop->screenGeometry(int screen_index)
根据当前的屏幕序号获取屏幕宽高等属性

4) int desktop->width()
获取虚拟屏幕全宽, 注意这个比较猛,是获取的总宽度,对于横向扩展屏来说,也就是 屏幕1+ 屏幕2 + … 的宽度
5) int desktop->height()
获取虚拟屏幕全高

下面的这个程序就可以测试多屏(只测了横屏,没测试纵屏): 根据当前屏幕数量n,生成n个窗口,每个窗口都占据了一个屏幕

#include "mainwindow.h"
#include <QApplication>
#include <QDesktopWidget>
#include <cstdio>
#include <QMessageBox>typedef struct{
int screen_no;
QRect rect;
}SCREEN;
SCREEN g_screens[10];int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDesktopWidget *desktop = QApplication::desktop();int screen_count = desktop->screenCount();int prim_screen = desktop->primaryScreen();
char warning[100], *idx=warning;
for(int i=0; i<screen_count ;i++ ){
g_screens[i].screen_no = prim_screen + i;
g_screens[i].rect = desktop->screenGeometry(prim_screen + i);
sprintf(idx, "screen%d w[%d], h[%d] ",i, g_screens[i].rect.width(),g_screens[i].rect.height() );
idx += strlen(idx);
}
sprintf(idx, "total width[%d] , total height[%d] n", desktop->width(), desktop->height() );
QMessageBox::warning(NULL, "screen", warning, QMessageBox::Ok);MainWindow wnd[5];
for(int i=0; i < screen_count; i++){
wnd[i].resize(g_screens[i].rect.width(),g_screens[i].rect.height());
if(i == 0)
wnd[i].move(0,0);
else
wnd[i].move(i* g_screens[i-1].rect.width(),0);
char str[50];
sprintf(str,"this is screen %d",i);
wnd[i].show();
}
return app.exec();
}

想实现这样一种功能:主程序的主窗口在PC上显示,而其子dialog在另外的显示器上显示(做实验时方便监控且不会有多余的干扰)。

方法如下 :建立Qdesktopwidget对象
QDesktopWidget* desktop = Application::desktop();

获取当前显示器的个数

N = desktop->screenCount();

如果有两个显示,则N=2,qt默认的计算机主机的index = 0,外接显示器的index = 1;
QDialog 有个成员函数叫setGeometry,只需要将dialog对象的Geometry设置为index为1的显示器即可,默认为0.如果要显示的dialog的对象为mdlg,则
mdlg.setGeometry(desktop->screenGeometry(1));
mdlg.show();

#include <QDesktopWidget>//获取屏幕信息
QDesktopWidget* desktop = QApplication::desktop();      //获取屏幕对象(这个函数必须在创建了 QApplication 对象之后才能使用, 否则会出错)                                                                                         
int screenNum = desktop->screenCount();         		//获取屏幕个数                                                                                  
int mainScreenID = desktop->primaryScreen();    		//获取主屏幕索引,(windows开始菜单所在的屏幕为主屏幕),每个副屏幕序号+1    
QRect screenRect = desktop->screenGeometry(int screen_index);	//根据屏幕索引获取屏幕宽高等属性
int screenWidth = desktop->width();						//获取屏幕的宽
int screenWidth = desktop->height();					//获取屏幕的高                                                                                                                                                                                                                                                                                                                                                                                                         
for(int i=0; i<screenNum; ++i) {         				//获取每块屏幕分辨率                                                                                           qDebug()<<"屏幕"<<i+1<<"分辨率: "<<desktop->screenGeometry(i).size();                                                                
}                                                                                                                                   //======================================================================   
//设置对话框mdlg显示在副屏1的左上角坐标
QDialog mdlg;
mdlg.setGeometry(desktop->screenGeometry(1));  
mdlg.show();  
//======================================================================   
//如果想全屏显示在副屏1,则可以获取副屏1的分辨率,更新对话框的大小再设置坐标
mdlg.resize(desktop->screenGeometry(1).size());		//设置对话框全屏
mdlg.setGeometry(desktop->screenGeometry(1)); 		//设置对话框对齐副屏1左上角坐标
mdlg.show();  
//======================================================================                                                                                                                         
linuxfb实现多屏(QT5已废弃)

如果多屏对应一个fb
那么应该可以知道不同屏对应fb显示内存的位置,只要根据位置去画窗口即可

如果多屏对应不同的设备 fb,可以运行下面的命令来指定不同的fb在qt显示内存上的位置
./xxx -qws -display "Mutli:LinuxFb:0 LinuxFb:/dev/fb1:1:offset=0,1080"
xxx表示qt可执行文件
"Mutli:LinuxFb:0 LinuxFb:/dev/fb1:1:offset=0,1080"
表示有两个输出fb分别是 /dev/fb0, /dev/fb1,其中/dev/fb0的起始位置在 qt 显示内存的(0,0), /dev/fb1的起始位置在 qt 显示内存的(0,1080)
程序中(假设显示分辨率为1920x1080)
在(0,0)到(1920,1080)范围内画窗口就显示在fb0上,在(0,1080)到 (1920,2160)范围画窗口就显示在fb1上

引申:内核态分配内存虚拟出一个fb0,操作fb0时,内核态程序将fb0内存复制到fb1和fb2内存中(前提是fb1和fb2的内核态地址即物理地址连续,且物理地址最好是固定的)。实际验证?

利用Qt实现双屏显示

前提是设备中有两个屏幕。这样在linux中Qt实现双屏显示就很简单了。只需要把窗口利用move函数移动到另一个屏幕的像素点就可以了。例如:一屏分辨率为:1280 * 800 ,二屏分辨率为:800 * 480。
(1)如果你定义了一个 1600 * 800的窗口,比一屏多出来400个像素点就会自动在二屏中显示,不用任何处理(前提是你到设备双屏能够正常运行)
(2)如果想在一屏的基础上点击一个按钮弹出一个窗口,而这个窗口想要在二屏上显示,就需要利用move函数,把这个对话框的位置移动到二屏上显示:move(1280,0);

对于上面的情况(1)(2),在linux上亲测没有问题,但是在ARM平台上出现问题:在点击了按钮后,窗口并没有在二屏上显示,而是在一屏中显示,而且置于最底层(原来的窗口挡住了这个窗口,因此并不能显示出来)。

在ARM设备中正常双屏显示如下:

#ifdef DOUBLE_SCREENdesktop = QApplication::desktop();
int N = desktop->screenCount();
qDebug()<<"screen :"<<N;
qDebug()<<"screen1 rect:"<<desktop->screenGeometry(0);
qDebug()<<"screen2 rect:"<<desktop->screenGeometry(1);DoubleScreen *m_DoubleScreen = new DoubleScreen;
m_DoubleScreen->initLab(desktop->screenGeometry(1));
m_DoubleScreen->show();#endifvoid DoubleScreen::initLab(QRect rect)
{setGeometry(rect);this->resize(800,480);lab=new QLabel("this is desktop"+QString::number(num+1),this);lab->setGeometry(0,0,rect.width(),rect.height());lab->setAlignment(Qt::AlignCenter) ;}

上述代码中DoubleScreen为继承QMainWindow的类,而initLab为他到成员函数,将二屏的rect作为initLab的参数传递进来,然后通过setGeometry()函数就能将DoubleScreen的窗口显示在二屏上了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/42301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring MVC 简介

目录 1. 什么是MVC2. 什么是SpringMVC 1. 什么是MVC MVC是一种常用的软件架构模式。可以看作是一种设计模式&#xff0c;也可以看作是一种软件框架。经典MVC模式中&#xff0c;M是指模型&#xff0c;V是视图&#xff0c;C则是控制器&#xff0c;使用MVC的目的是将M和V的实现代…

golang中使用chan控制协程并发简单事例

func main() {processNum : 5ch : make(chan struct{}, processNum)for true {ch <- struct{}{}go func() {defer func() {<-ch}()fmt.Println("我是协程", time.Now().UnixNano())time.Sleep(time.Second * 5)}()} } 可以看到&#xff0c;这里每5s会执行一次带…

Linux15 消息队列 线程

目录 1、进程间通信IPC&#xff1a; 2、多线程 3、向消息队列中写入数据 4、从消息队列中读取数据 5、多线程&#xff1a; 6、将多线程的数据返回给主…

数据库索引优化策略与性能提升实践

文章目录 什么是数据库索引&#xff1f;为什么需要数据库索引优化&#xff1f;数据库索引优化策略实践案例&#xff1a;索引优化带来的性能提升索引优化规则1. 前导模糊查询不适用索引2. 使用IN优于UNION和OR3. 负向条件查询不适用索引4. 联合索引最左前缀原则5. 范围条件查询右…

【Mysql】MVCC版本机制的多并发

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

PostgreSQL空值的判断

PostgreSQL空值的判断 空值判断非空判断总结 空值判断 -- 查询为空的 is null,sql简写isnull select * from employees where manager_id isnull;select * from employees where manager_id is null;非空判断 -- 查询不为空的 is not null;sql简写notnull select * from empl…

Java【数据结构】二分查找

&#x1f31e; 题目&#xff1a; &#x1f30f;在有序数组A中&#xff0c;查找目标值target &#x1f30f;如果找到返回索引 &#x1f30f;如果找不到返回-1 算法描述解释前提给定一个内含n个元素的有序数组A&#xff0c;满足A0<A1<A2<<An-1,一个待查值target1设…

mysql 8.0安装

操作系统&#xff1a;22.04.1-Ubuntu apt 安装命令 sudo apt install mysql-client-core-8.0 sudo apt install mysql-server-8.0终端输入 mysql 可以直接免密登录 如果此时提示需要密码&#xff0c;则可以进入配置文件&#xff0c;设置免密登录 sudo vim /etc/mysql/mysq…

【探索Linux】—— 强大的命令行工具 P.5(yum工具、git 命令行提交代码)

阅读导航 前言一、软件包管理器 yum1.yum的概念yum的基本指令使用例子 二、git 命令行提交代码总结温馨提示 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff0c;也学习了一些Linux的基本操作&#xff0c;也了…

20W IP网络吸顶喇叭 POE供电吸顶喇叭

SV-29852T 20W IP网络吸顶喇叭产品简介 产品用途&#xff1a; ◆室内豪华型吸顶喇叭一体化网络音频解码扬声器&#xff0c;用于广播分区音频解码、声音还原作用 ◆应用场地如火车站、地铁、教堂、工厂、仓库、公园停车场等&#xff1b;室内使用效果均佳。 产品特点&#xff…

pytorch_lightning报错 You requested gpu: [1],But your machine only has: [0]

pytorch_lightning报错 You requested gpu: [1]&#xff0c;But your machine only has: [0] 问题及分析 报错图片如下&#xff1a; 分析 gpu:[1]指代的gpu的标号&#xff0c;如果笔记本中只包含一个GPU&#xff0c;一般序号为[0].所以无法找到程序指定的GPU。 解决方法 …

编程语言学习笔记-架构师和工程师的区别,PHP架构师之路

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

Egg.js构建一个stream流式接口服务

经常需要用到 stream 流式接口服务,比如&#xff1a;大文件下载、日志实时输出等等。本文将介绍如何使用Egg.js构建一个 stream 流式接口服务。 一、准备工作 目录结构&#xff1a; app//controllerindex.jstest.txttest.shindex.js 控制器test.txt 测试文件&#xff0c;最好…

5G+AI数字化智能工厂建设解决方案PPT

导读&#xff1a;原文《5GAI数字化智能工厂建设解决方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。数字化智能工厂定义 智能基础架构协同框架 - 端、边、云、网…

激光雷达 01 线数

一、线数 对于 360 旋转式和一维转镜式架构的激光雷达来说&#xff0c;有几组激光收发模块&#xff0c;垂直方向上就有几条线&#xff0c;被称为线数。这种情况下&#xff0c;线数就等同于激光雷达内部激光器的数量[参考]。 通俗来讲&#xff0c;线数越高&#xff0c;激光器的…

npm run xxx 的时候发生了什么?(以npm run dev举例说明)

文章目录 一、去package.json寻找scripts对应的命令二、去node_modules寻找vue-cli-service三、从package-lock.json获取.bin的软链接1. bin目录下的那些软连接存在于项目最外层的package-lock.json文件中。2.vue-cli-service文件的作用3.npm install 的作用 总结 一、去packag…

Google API实战与操作

Google api实战与操作 一. Google API 权限配置二. 操作API2.1 引入依赖2.2 导入代码 Google官网 实现一套用java程序控制GoogleAPI实现自动生成监控日报等功能,具体能操作Gsheet及document 一. Google API 权限配置 打开上面官网,新建项目 启用API 搜索sheet及document …

【山河送书第七期】:《强化学习:原理与Python实战》揭秘大模型核心技术RLHF!

《强化学习&#xff1a;原理与Python实战》揭秘大模型核心技术RLHF&#xff01; 一图书简介二RLHF是什么&#xff1f;三RLHF适用于哪些任务&#xff1f;四RLHF和其他构造奖励模型的方法相比有何优劣&#xff1f;五什么样的人类反馈才是好反馈&#xff1f;六如何减小人类反馈带来…

web前端开发基础入门html5+css3+js学习笔记(一)

目录 1.第一个前端程序2.前端工具的选择与安装3.VSCode开发者工具快捷键4.HTML5简介与基础骨架4.1 HTML5的DOCTYPE声明4.2 HTML5基本骨架4.2.1 html标签4.2.2 head标签4.2.3 body标签4.2.4 title标签4.2.5 meta标签 5.标签之标题5.1 快捷键5.1 标题标签位置摆放 6.标签之段落、…

leetcode 377. 组合总和 Ⅳ

2023.8.17 本题属于完全背包问题&#xff0c;乍一看和昨天那题 零钱兑换II 类似&#xff0c;但细看题目发现&#xff1a;今天这题是排列问题&#xff0c;而“零钱兑换II”是组合问题。排列问题强调顺序&#xff0c;而组合顺序不强调顺序。 这里先说个结论&#xff1a;先遍历物品…