You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt双屏实时显示与录制需求:寻求QLabels展示及录屏存储最优方案

Hey there! Let's fix your dual-screen real-time display issue first, then add the screen recording feature you need. I'll break this down step by step.

First: Fix the "Picture-in-Picture" & Dual-Screen Display Problem

Your earlier code had two main issues causing the weird display behavior:

  1. Calling on_pbtn_stop_clicked() (which clears the label) every time you capture a frame creates unnecessary flickering and potential overlap.
  2. You weren't targeting individual screens—you only grabbed the primary screen, and didn't account for the second display's geometry.

Here's the revised code to handle dual-screen real-time display properly:

1. Update Your Header (ScreenCapture.h)

Add necessary declarations for the timer and screen handling:

#ifndef SCREENCAPTURE_H
#define SCREENCAPTURE_H

#include <QWidget>
#include <QTimer>
#include <QScreen>
#include <QPixmap>

QT_BEGIN_NAMESPACE
namespace Ui { class ScreenCapture; }
QT_END_NAMESPACE

class ScreenCapture : public QWidget
{
    Q_OBJECT

public:
    ScreenCapture(QWidget *parent = nullptr);
    ~ScreenCapture();

private slots:
    void on_pbtn_start_clicked();
    void on_pbtn_stop_clicked();
    void captureAndUpdateScreens(); // New slot for dual-screen capture

private:
    Ui::ScreenCapture *ui;
    QTimer *captureTimer;
};
#endif // SCREENCAPTURE_H

2. Update Your Implementation (ScreenCapture.cpp)

#include "ScreenCapture.h"
#include "ui_ScreenCapture.h"

ScreenCapture::ScreenCapture(QWidget* parent)
    : QWidget(parent)
    , ui(new Ui::ScreenCapture)
{
    ui->setupUi(this);

    // Configure labels to scale captured frames to fit their size
    ui->Label1->setScaledContents(true);
    ui->Label2->setScaledContents(true);

    // Initialize timer for ~30fps capture
    captureTimer = new QTimer(this);
    captureTimer->setInterval(33); // 1000ms / 30 ≈ 33ms
    connect(captureTimer, &QTimer::timeout, this, &ScreenCapture::captureAndUpdateScreens);
}

ScreenCapture::~ScreenCapture()
{
    delete ui;
    delete captureTimer;
}

void ScreenCapture::on_pbtn_start_clicked()
{
    captureTimer->start();
}

void ScreenCapture::on_pbtn_stop_clicked()
{
    captureTimer->stop();
    // Clear both labels when stopping
    ui->Label1->clear();
    ui->Label2->clear();
}

void ScreenCapture::captureAndUpdateScreens()
{
    QList<QScreen*> screens = QGuiApplication::screens();
    if (screens.size() < 2) {
        // Handle case where only one screen is available
        return;
    }

    // Capture and update first screen (display1)
    QScreen* screen1 = screens[0];
    const QRect screen1Geom = screen1->geometry();
    QPixmap pixmap1 = screen1->grabWindow(0, 
        screen1Geom.x(), screen1Geom.y(),
        screen1Geom.width(), screen1Geom.height());
    ui->Label1->setPixmap(pixmap1);

    // Capture and update second screen (display2)
    QScreen* screen2 = screens[1];
    const QRect screen2Geom = screen2->geometry();
    QPixmap pixmap2 = screen2->grabWindow(0,
        screen2Geom.x(), screen2Geom.y(),
        screen2Geom.width(), screen2Geom.height());
    ui->Label2->setPixmap(pixmap2);
}

Key fixes here:

  • No more clearing labels before updating—this eliminates flickering and the "picture-in-picture" effect
  • We explicitly target each screen's geometry with grabWindow() to capture only that display's content
  • Labels are set to scale frames to fit their size, so you don't get cropped content

Second: Add Screen Recording Functionality

For recording, Qt 6.2+ introduced QScreenCapture which makes this straightforward. If you're using Qt 5, you'll need to use a third-party library like FFmpeg or OpenCV to encode frames into a video, but I'll cover the Qt 6 approach first.

1. Update Header with Recording Classes

// Add these includes to ScreenCapture.h
#include <QScreenCapture>
#include <QMediaRecorder>
#include <QMediaEncoderSettings>

// Add these members to the private section
QScreenCapture *screenCapture1;
QScreenCapture *screenCapture2;
QMediaRecorder *recorder1;
QMediaRecorder *recorder2;

2. Initialize Recording Objects in Constructor

Add this to your ScreenCapture constructor:

// Initialize screen capture objects for each display
QList<QScreen*> screens = QGuiApplication::screens();
if (screens.size() >= 2) {
    screenCapture1 = new QScreenCapture(screens[0], this);
    screenCapture2 = new QScreenCapture(screens[1], this);

    // Set up recorders for each screen
    recorder1 = new QMediaRecorder(this);
    recorder2 = new QMediaRecorder(this);

    recorder1->setSource(screenCapture1);
    recorder2->setSource(screenCapture2);

    // Configure recording settings (MP4 format, 30fps)
    QMediaEncoderSettings encoderSettings;
    encoderSettings.setCodec("video/mp4");
    encoderSettings.setFrameRate(30);

    // Set output for screen 1
    encoderSettings.setResolution(screens[0]->geometry().size());
    recorder1->setEncoderSettings(encoderSettings);
    recorder1->setOutputLocation(QUrl::fromLocalFile("./screen1_recording.mp4"));

    // Set output for screen 2
    encoderSettings.setResolution(screens[1]->geometry().size());
    recorder2->setEncoderSettings(encoderSettings);
    recorder2->setOutputLocation(QUrl::fromLocalFile("./screen2_recording.mp4"));
}

3. Add Start/Stop Recording Slots

Add these slots to handle recording controls:

// Add these declarations to ScreenCapture.h private slots
void on_pbtn_start_record_clicked();
void on_pbtn_stop_record_clicked();

// Implement in ScreenCapture.cpp
void ScreenCapture::on_pbtn_start_record_clicked()
{
    if (screenCapture1 && recorder1) {
        screenCapture1->start();
        recorder1->record();
    }
    if (screenCapture2 && recorder2) {
        screenCapture2->start();
        recorder2->record();
    }
}

void ScreenCapture::on_pbtn_stop_record_clicked()
{
    if (recorder1 && recorder1->isRecording()) {
        recorder1->stop();
        screenCapture1->stop();
    }
    if (recorder2 && recorder2->isRecording()) {
        recorder2->stop();
        screenCapture2->stop();
    }
}

If you're stuck on Qt 5, you can modify the captureAndUpdateScreens() slot to save each QPixmap to a list, then use OpenCV's cv::VideoWriter to encode the list into a video file. Just convert each QPixmap to an OpenCV Mat first.


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:55:38