嵌入式Qt:使用QGraphicsView与QGraphicsWidget实现双屏显示
Qt 4.8下基于QGraphicsView/QGraphicsWidget的双屏实现方案
我刚好有过在Qt 4.8里用QGraphics框架做双屏显示的经验,给你整理了一套完整的实现思路和代码示例,结合双帧缓冲区来满足你的需求:
核心思路
虽然QDesktopWidget主要是给QWidget用的,但我们可以借助它获取屏幕的几何信息,然后为每个屏幕创建独立的QGraphicsView实例,再通过离线帧缓冲区(用QPixmap或QImage)先绘制内容,最后把绘制好的内容放到对应的QGraphicsScene中显示。这样既贴合你基于QGraphicsWidget的控件体系,也能实现双屏控制。
分步实现&代码示例
1. 先获取屏幕的几何信息
首先用QDesktopWidget拿到系统的屏幕数量和每个屏幕的位置、大小,这一步是通用的,和QWidget体系无关:
#include <QApplication> #include <QDesktopWidget> #include <QList> QDesktopWidget* desktop = QApplication::desktop(); int screenCount = desktop->screenCount(); QList<QRect> screenRects; // 遍历所有屏幕,记录每个屏幕的几何区域 for(int i = 0; i < screenCount; ++i){ screenRects.append(desktop->screenGeometry(i)); }
2. 为每个屏幕创建独立的QGraphicsView
每个屏幕对应一个全屏的QGraphicsView窗口,设置无边框以实现全屏显示:
#include <QGraphicsView> #include <Qt> // 假设我们有两个屏幕,创建两个View实例 QGraphicsView* screen1View = new QGraphicsView(); QGraphicsView* screen2View = new QGraphicsView(); // 配置第一个屏幕的View:全屏、无边框 screen1View->setGeometry(screenRects.at(0)); screen1View->setWindowFlags(Qt::FramelessWindowHint); screen1View->show(); // 配置第二个屏幕的View screen2View->setGeometry(screenRects.at(1)); screen2View->setWindowFlags(Qt::FramelessWindowHint); screen2View->show();
3. 双帧缓冲区的离线绘制实现
用QPixmap作为离线绘制的帧缓冲,先在缓冲里完成所有绘制操作,再把缓冲内容添加到QGraphicsScene中,这样能提升绘制性能:
#include <QGraphicsScene> #include <QPixmap> #include <QPainter> // 为每个View创建独立的Scene QGraphicsScene* screen1Scene = new QGraphicsScene(screen1View); QGraphicsScene* screen2Scene = new QGraphicsScene(screen2View); screen1View->setScene(screen1Scene); screen2View->setScene(screen2Scene); // 创建对应屏幕分辨率的帧缓冲 QPixmap frameBuffer1(screenRects.at(0).size()); QPixmap frameBuffer2(screenRects.at(1).size()); // 离线绘制第一个屏幕的内容 QPainter painter1(&frameBuffer1); painter1.fillRect(frameBuffer1.rect(), Qt::darkBlue); painter1.setPen(Qt::white); painter1.drawText(150, 150, "Screen 1 - QGraphics Content"); painter1.end(); // 离线绘制第二个屏幕的内容 QPainter painter2(&frameBuffer2); painter2.fillRect(frameBuffer2.rect(), Qt::darkGreen); painter2.setPen(Qt::white); painter2.drawText(150, 150, "Screen 2 - QGraphics Content"); painter2.end(); // 将帧缓冲添加到Scene中作为显示项 screen1Scene->addPixmap(frameBuffer1); screen2Scene->addPixmap(frameBuffer2);
4. 集成自定义QGraphicsWidget控件
如果你的控件都是基于QGraphicsWidget开发的,直接把这些控件添加到对应屏幕的QGraphicsScene即可,比如自定义一个简单的控件:
#include <QGraphicsWidget> #include <QPainter> class CustomGraphicsWidget : public QGraphicsWidget { protected: void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) { painter->setBrush(Qt::red); painter->drawRect(boundingRect()); painter->setPen(Qt::white); painter->drawText(boundingRect(), Qt::AlignCenter, "Custom Widget"); } }; // 添加到第一个屏幕的Scene CustomGraphicsWidget* widget1 = new CustomGraphicsWidget(); widget1->setPos(250, 250); widget1->resize(350, 200); screen1Scene->addItem(widget1); // 添加到第二个屏幕的Scene CustomGraphicsWidget* widget2 = new CustomGraphicsWidget(); widget2->setPos(450, 350); widget2->resize(350, 200); screen2Scene->addItem(widget2);
5. 动态更新帧缓冲(实时内容场景)
如果需要实时刷新双屏内容,可以用QTimer定时更新帧缓冲,然后同步到Scene中:
#include <QTimer> #include <QTime> // 创建定时器,约60fps刷新 QTimer* updateTimer = new QTimer(this); connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameBuffers())); updateTimer->start(16); // 定时器槽函数,更新双屏内容 void updateFrameBuffers() { // 更新第一个屏幕的帧缓冲 frameBuffer1.fill(Qt::darkBlue); QPainter painter1(&frameBuffer1); painter1.setPen(Qt::white); painter1.drawText(150, 150, QString("Screen 1 - Current Time: %1").arg(QTime::currentTime().toString())); painter1.end(); // 更新Scene中的Pixmap项 static_cast<QGraphicsPixmapItem*>(screen1Scene->items().first())->setPixmap(frameBuffer1); // 更新第二个屏幕的帧缓冲 frameBuffer2.fill(Qt::darkGreen); QPainter painter2(&frameBuffer2); painter2.setPen(Qt::white); painter2.drawText(150, 150, QString("Screen 2 - Current Time: %1").arg(QTime::currentTime().toString())); painter2.end(); static_cast<QGraphicsPixmapItem*>(screen2Scene->items().first())->setPixmap(frameBuffer2); }
关键注意事项
- 屏幕适配:Qt 4.8中
QDesktopWidget::screenGeometry()能准确获取多屏的位置和分辨率,确保View能精准显示在目标屏幕上。 - 性能优化:离线帧缓冲能减少直接在UI线程绘制的开销,尤其是复杂场景下,建议把耗时的绘制操作放到帧缓冲里完成。
- 事件交互:
QGraphicsWidget的事件(比如点击、拖拽)会被Qt自动分发到对应的QGraphicsView和QGraphicsScene,不需要额外处理。 - 多线程绘制(可选):如果绘制任务很重,可以把帧缓冲的绘制逻辑放到子线程,完成后再通过信号槽把绘制好的
QPixmap传递到主线程更新Scene,避免UI卡顿。
内容的提问来源于stack exchange,提问作者user1521589




