QT多屏显示程序

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

多屏虚拟成一个桌面,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.rhkb.cn/news/94768.html

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

相关文章

阿里云Linux服务器安装FTP站点全流程

阿里云百科分享使用阿里云服务器安装FTP全教程&#xff0c;vsftpd&#xff08;very secure FTP daemon&#xff09;是Linux下的一款小巧轻快、安全易用的FTP服务器软件。本教程介绍如何在Linux实例上安装并配置vsftpd。 目录 前提条件 步骤一&#xff1a;安装vsftpd 步骤二…

轻松学会网络编程

目录 一、UDP 和 TCP 特点对比 1、有连接和无连接 2、可靠传输和不可靠传输 3、面向字节流和面向数据报 4、全双工和半双工 二、UDP 的 socket.api 1、DatagramSocket 2、DatagramPacket 回显服务器的实现 &#xff08;1&#xff09;服务器代码 &#xff08;2&#…

如何应用项目管理软件进行敏捷开发管理

敏捷开发&#xff08;Agile Development&#xff09;是一种软件开发方法论&#xff0c;强调在不断变化的需求和环境下&#xff0c;通过迭代、协作和自适应的方式来开发软件。敏捷方法的目标是提供更快、更灵活、更高质量的软件交付&#xff0c;以满足客户需求并实现项目成功。 …

LeetCode150道面试经典题-- 汇总区间(简单)

1.题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,…

力扣 198. 打家劫舍

题目来源&#xff1a;https://leetcode.cn/problems/house-robber/description/ C题解&#xff1a;因为是间接偷窃&#xff0c;所以偷nums[i]家前&#xff0c;一定偷过第i-2或者i-3家&#xff0c;因为i-1不能偷。 例如12345共5家&#xff0c;先偷第1家&#xff0c;那么2不能偷…

数据结构-栈的实现(C语言版)

前言 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除的操作&#xff0c;进行数据插入和删除的一端叫做栈顶&#xff0c;另一端叫做栈底。 栈中的数据元素遵循后进先出的的原则。 目录 1.压栈和出栈 2. 栈的实现 3.测试代码 1.压栈和出栈 压栈&#xff…

vue 使用indexDB 简单完整逻辑

1 npm npm install idb 2 代码 <template><div><p>Data: {{ data }}</p><button click"fetchData">Fetch Data</button></div> </template><script> import { openDB } from idb;export default {data() {…

【C++学习手札】一文带你认识C++虚函数(内层剖析)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f340;本文前置知识&#xff1a; C初识继承 ♈️今日夜电波&#xff1a;No title —REOL 1:02 ━━━━━━️&#x1f49f;──────── 4:03 …

PHP手术麻醉系统源码,自动生成麻醉和护理医疗文书

一套手术麻醉系统源码&#xff0c;可二次开发 手术室麻醉临床信息系统&#xff08;AIMS&#xff09;是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期&#xff0c;对病人进行全程跟踪与信息管理&#xff0c;自动集成病人HIS、LIS、RIS、PACS信息&#xff0…

ts与vue

ts与Vue 如果你已经学习了typeScript,但不知道如何在vue项目中使用&#xff0c;那么这篇文章将会很适合你。参考千峰教育 kerwin视频 1.会自动推导&#xff0c;隐士推导。提示 类型系统。 独立模块。 isolatedModules选项&#xff1a;是否配置为独立的模块。 减少报错 let …

数字化时代,数据仓库和商业智能BI系统演进的五个阶段

数字化在逐渐成熟的同时&#xff0c;社会上也对数字化的性质有了进一步认识。当下&#xff0c;数字化除了前边提到的将复杂的信息、知识转化为可以度量的数字、数据&#xff0c;在将其转化为二进制代码&#xff0c;引入计算机内部&#xff0c;建立数据模型&#xff0c;统一进行…

FPGA芯片IO口上下拉电阻的使用

FPGA芯片IO口上下拉电阻的使用 为什么要设置上下拉电阻一、如何设置下拉电阻二、如何设置上拉电阻为什么要设置上下拉电阻 这里以高云FPGA的GW1N-UV2QN48C6/I5来举例,这个芯片的上电默认初始化阶段,引脚是弱上来模式,且模式固定不能通过软件的配置来改变。如下图所示: 上…

华为OD机试 - 查找接口成功率最优时间段 - 回溯(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

Viobot开机指南

0.前言 本篇旨在让每个拿到Viobot设备的用户都能够第一时间测试它的效果&#xff0c;以及将设备配置到自己的环境下面。 1.上电 首先&#xff0c;我们先要把设备接上电源线和网线&#xff0c;最简单的方式就是网线直连电脑。 电源选用12V1.5A设备自带的电源即可。 2.配置网…

Android 网络编程-网络请求

Android 网络编程-网络请求 文章目录 Android 网络编程-网络请求一、主要内容二、开发网络请求前的基本准备1、查看需要请求的网址是否有效&#xff08;1&#xff09;通过网页在线验证&#xff08;2&#xff09;使用专用window网咯请求工具&#xff08;3&#xff09;编写app代码…

《游戏编程模式》学习笔记(四) 观察者模式 Observer Pattern

定义 观察者模式定义了对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 这是定义&#xff0c;看不懂就看不懂吧&#xff0c;我接下来举个例子慢慢说 为什么我们需要观察者模式 我们看一个很简…

ubuntu部署haproxy

HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理. 1、更新系统报 通过在终端中运行以下命令&#xff0c;确保所有系统包都是最新的 sudo apt updatesudo apt upgrade2、安装Haproxy sudo apt install haproxy设置开机自动启动haproxy服务 sudo systemctl en…

微服务-Nacos(注册中心)

Nacos是SpringCloud的一个功能非常强大的组件&#xff0c;想比eureka的功能更加丰富 官方的nacos简介 Nacos&#xff08;全称&#xff1a;Naming and Configuration Service&#xff09;是一个开源的动态服务发现、配置管理和服务管理平台。它由阿里巴巴集团开发并贡献给开源…

SpringBoot复习:(51)默认情况下DataSource是怎么创建出来的,是什么类型的?

DataSource是通过DataSourceAutoConfiguration创建的&#xff0c;这个类代码如下&#xff1a; 可以看到DataSourceAutoConfiguration有个静态内部类PooledDataSourceConfiguration,在这个类上有个Import注解&#xff0c;导入了DataSourceConfiguration.Hikari这个类&#xff0…

【学习日记】【FreeRTOS】任务调度时如何考虑任务优先级——任务的自动切换

写在前面 本文开始为 RTOS 加入考虑任务优先级的自动调度算法&#xff0c;代码大部分参考野火。 本文主要是一篇学习笔记&#xff0c;加入了笔者自己对野火代码的梳理和理解。 一、基本思路 首先我们要知道&#xff0c;在 RTOS 中&#xff0c;优先级越高、越需要被先执行的的…