You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

嵌入式Qt:使用QGraphicsView与QGraphicsWidget实现双屏显示

Qt 4.8下基于QGraphicsView/QGraphicsWidget的双屏实现方案

我刚好有过在Qt 4.8里用QGraphics框架做双屏显示的经验,给你整理了一套完整的实现思路和代码示例,结合双帧缓冲区来满足你的需求:

核心思路

虽然QDesktopWidget主要是给QWidget用的,但我们可以借助它获取屏幕的几何信息,然后为每个屏幕创建独立的QGraphicsView实例,再通过离线帧缓冲区(用QPixmapQImage)先绘制内容,最后把绘制好的内容放到对应的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自动分发到对应的QGraphicsViewQGraphicsScene,不需要额外处理。
  • 多线程绘制(可选):如果绘制任务很重,可以把帧缓冲的绘制逻辑放到子线程,完成后再通过信号槽把绘制好的QPixmap传递到主线程更新Scene,避免UI卡顿。

内容的提问来源于stack exchange,提问作者user1521589

火山引擎 最新活动