Qt WindowFlags属性详解 - 一杯清酒邀明月
(10条消息) QT学习笔记(七)——使用QCamera来显示捕获的视频_马大哈先生的博客-
Qt 摄像头显示
- 访问摄像机需要添加
Qt Multimedia
模块
Qt多媒体是一个必不可少的模块,它提供了一组丰富的QML类型和C++类来处理多媒体内容。它还提供必要的 API 来访问摄像机和无线电功能。随附的Qt音频引擎提供3D位置音频播放和内容管理类型。
QT += multimedia multimediawidgets
代码化 UI 设计
- UI设计使用代码进行设计,需要注意的一点是:
- 此 demo 中的窗口为
MainWindow
继承自QMainWindow
默认是有 layout(布局) 的。 - 一般的方法声明一个
mainLayout
,然后不停地把各个布件或布局放入mainLayout
中,最后调用窗口的成员函数setLayout(mainLayout)
就行。 - 由于
QMainWindow
有默认布局,再次用setLayout(mainLayout)
设置布局,会提示操作失败:
QWidget::setLayout: Attempting to set QLayout "" on MainWindow "", which already has a layout
这里的解决办法:
QWidget* centralWidget = new QWidget;
centralWidget->setLayout(mainLayout);
this->setCentralWidget(centralWidget);
项目代码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QComboBox>
#include <QPushButton>
#include <QtMultimedia/QCamera>
#include <QtMultimedia/QCameraInfo>
#include <QtMultimediaWidgets/QCameraViewfinder>
#include <QtMultimedia/QCameraImageCapture>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QList>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
QWidget* centralWidget;
QLabel* m_Label;
QComboBox* comboCamera; ///< 显示相机列表的组合框
QPushButton* refreshButton; ///< 刷新相机列表按钮
QPushButton* imageCaptureButton; ///< 抓拍按钮
QCameraViewfinder* viewFinder; ///< 取景器对象,用于镜头显示
QCamera* camera_1 = nullptr; ///< 相机对象
QCameraImageCapture* imageCapture = nullptr; ///< 抓图对象
QList<QCameraInfo> cameras; ///< 相机列表
/// UI 创建与初始化
void initUI();
/// 获取所选择的相机的信息
void getCameraInfo(int index);
/// 初始化信号与槽的连接
void initSignalSlots();
/// 初始化抓图对象
void initImageCapture();
private slots:
/// 刷新按钮刷新相机列表的槽函数
void refreshCameraList();
/// 初始化相机对象
/// 初始化相机对象,并在 videoWidget 显示相机画面
/// @param cameraInfo 要初始化并显示的相机的对应信息对象
void initCamera(const QCameraInfo& cameraInfo);
/// 抓图槽函数
void captureImage();
signals:
/// 将选择好的相机信息对象作为信号发送出去
void CameraInfo(QCameraInfo cameraInfo);
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QtMultimedia/QCameraViewfinderSettings>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
initUI(); // UI 初始化
refreshCameraList(); // 获取可用相机列表
initSignalSlots(); // 连接信号与槽
initCamera(cameras[0]); // 默认显示第一个摄像头
// 置顶窗口
this->setWindowFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);
}
MainWindow::~MainWindow()
{
}
void MainWindow::initUI()
{
this->setFixedSize(1024, 600);
// 创建m_Label、comboCamera、refreshButton、imageCaptureButton 并水平布局
m_Label = new QLabel;
m_Label->setText("选择相机");
comboCamera = new QComboBox;
refreshButton = new QPushButton;
refreshButton->setText("刷新列表");
imageCaptureButton = new QPushButton;
imageCaptureButton->setText("抓拍");
QHBoxLayout* Hlay = new QHBoxLayout;
Hlay->addWidget(m_Label);
Hlay->addWidget(comboCamera);
Hlay->addWidget(refreshButton);
Hlay->addWidget(imageCaptureButton);
// 创建垂直布局,加入 videoWidget 和 Hlay
viewFinder = new QCameraViewfinder;
QVBoxLayout* Vlay = new QVBoxLayout;
Vlay->addLayout(Hlay);
Vlay->addWidget(viewFinder);
// 设置中心窗口
centralWidget = new QWidget;
centralWidget->setLayout(Vlay);// 设置中心窗口的布局
setCentralWidget(centralWidget);
}
void MainWindow::refreshCameraList()
{
comboCamera->clear();
// 获取相机列表
cameras = QCameraInfo::availableCameras();
// 使用 comboCamera 组合框显示相机列表
foreach(const QCameraInfo& info, cameras)
{
comboCamera->addItem(info.description());
}
}
void MainWindow::getCameraInfo(int index)
{
emit CameraInfo(cameras[index]);
}
void MainWindow::initCamera(const QCameraInfo& cameraInfo)
{
// 切换摄像头必须 delete 原来的 camera_1
// 否则,会造成内存泄漏
if(camera_1 != nullptr)
{
camera_1->unload();
delete camera_1;
camera_1 = nullptr;
}
camera_1 = new QCamera(cameraInfo,this);
// 取景器设置对象用于指定QCamera 使用的取景器设置
QCameraViewfinderSettings viewfinderSettings;
viewfinderSettings.setResolution(640,480);// 设置分辨率
viewfinderSettings.setMaximumFrameRate(15.0);// 设置最小帧率为 15
viewfinderSettings.setMaximumFrameRate(30.0);// 设置最大帧率为 30
camera_1->setViewfinderSettings(viewfinderSettings);
camera_1->setViewfinder(viewFinder);// 设置在 videoWidget 显示画面
// QCamera::CaptureMode
// QCamera::CaptureViewfinder 取景器,简单的画面显示
// QCamera::CaptureStillImage 帧捕获模块,如拍照
// QCamera::CaptureVideo 视频捕获模式,如录制视频,Windows 下不支持
camera_1->setCaptureMode(QCamera::CaptureViewfinder);// 取景器
if(!camera_1->isCaptureModeSupported(QCamera::CaptureStillImage))
{
qDebug() << "当前相机不支持拍照!";
imageCaptureButton->setDisabled(true);
}
else
{
camera_1->setCaptureMode(QCamera::CaptureStillImage);
initImageCapture();
}
camera_1->start();// 开启摄像头
}
void MainWindow::initImageCapture()
{
if(imageCapture != nullptr)
{
delete imageCapture;
imageCapture = nullptr;
}
imageCapture = new QCameraImageCapture(camera_1, this);
imageCapture->setBufferFormat(QVideoFrame::Format_Jpeg);// 缓冲区格式
imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);// 保存目标
}
void MainWindow::captureImage()
{
imageCapture->capture();
}
void MainWindow::initSignalSlots()
{
// 刷新相机列表按钮
connect(refreshButton, &QPushButton::clicked, this, &MainWindow::refreshCameraList);
// 选择显示不同的相机
// QComboBox::activated 信号函数有重载,activated(int) 和 activeted(const QString&)
// 因此需要用 QOverload 来确定重载函数的指针
connect(comboCamera, QOverload<int>::of(&QComboBox::activated), this, &MainWindow::getCameraInfo);
// 发出相机信息后,就显示对应的相机
connect(this, &MainWindow::CameraInfo, this, &MainWindow::initCamera);
// 抓拍按钮
connect(imageCaptureButton, &QPushButton::clicked, this, &MainWindow::captureImage);
}
- PS:抓拍的图片默认在电脑的「图片文件夹」中
效果