使用QT实现Mjpeg-streamer的客户端,采用单独的线程进行视频图片的获取
1. mjpeg-streamer服务器的搭建
- 在树莓派上搭建好mjpeg-streamer的服务器,搭建过程可以参考这篇文章mjpg-streamer在树莓派上的使用
2. 简单QT界面的设计
- QT的界面布局主要参考了这篇文章,但是我的里面是使用单独开辟的线程进行解析数据流的,这个文章里面是在主线程中完成的。QT界面设计.
3. 使用线程获取网络图片
- 使用线程会遇到很多的问题,可以参考这篇文章QT 多线程采用线程池进行网络操作
4. 源码
1. 主函数
#include "loginwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
LoginWindow w;
w.setWindowFlags(Qt::FramelessWindowHint);
w.show();
return a.exec();
}
2. 登录窗口界面代码
1. loginwindow.h
#ifndef LOGINWINDOW_H
#define LOGINWINDOW_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QTimer>
#include "mainwindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class LoginWindow; }
QT_END_NAMESPACE
class LoginWindow : public QMainWindow
{
Q_OBJECT
public:
LoginWindow(QWidget *parent = nullptr);
~LoginWindow();
private slots:
void timerFinish();
void on_btn_login_clicked();
void on_btn_logout_clicked();
private:
Ui::LoginWindow *ui;
QString login_ipAddr;
QString login_port;
int waitCnt;
QTimer *time;
QString text;
QTcpSocket *tcpClient;
MainWindow *main;
void init();
};
#endif // LOGINWINDOW_H
2. loginwindow.cpp
#include "loginwindow.h"
#include "ui_loginwindow.h"
#include <QMessageBox>
LoginWindow::LoginWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::LoginWindow)
{
ui->setupUi(this);
waitCnt = 0;
text.append("Login");
init();
}
LoginWindow::~LoginWindow()
{
delete ui;
}
void LoginWindow::init()
{
this->setWindowTitle("Please to Login");
ui->le_ipAddr->setText("219.216.115.53");
ui->le_port->setText("8080");
}
void LoginWindow::timerFinish()
{
if(tcpClient->state() == QTcpSocket::ConnectedState){
waitCnt = 0;
time->stop();
this->close();
main = new MainWindow;
main->main_ipAddr = login_ipAddr;
main->main_port = login_port;
main->init();
main->show();
}else{
waitCnt++;
if(waitCnt%10 == 3)
text = "Login.";
else if(waitCnt%10 == 6)
text = "Login..";
else if(waitCnt%10 == 9)
text = "Login...";
ui->btn_login->setText(text);
if(waitCnt == 50){
time->stop();
waitCnt = 0;
ui->btn_login->setText("Login");
QMessageBox::warning(this, "Warning", "Please to Check params\nand Login again!", QMessageBox::Ok);
}
}
}
void LoginWindow::on_btn_login_clicked()
{
login_ipAddr = ui->le_ipAddr->text();
login_port = ui->le_port->text();
tcpClient = new QTcpSocket(this);
tcpClient->connectToHost(login_ipAddr, login_port.toInt());
time = new QTimer(this);
time->setInterval(100);
connect(time, SIGNAL(timeout()), this, SLOT(timerFinish()));
time->start();
}
void LoginWindow::on_btn_logout_clicked()
{
this->close();
}
3. 主窗口界面代码
1. mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPixmap>
#include "getpixmap.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
QString main_ipAddr;
QString main_port;
void init();
private slots:
void on_btn_start_clicked();
void on_btn_screenshot_clicked();
void on_btn_quit_clicked();
void main_getOnePixmap(QPixmap);
private:
Ui::MainWindow *ui;
bool main_state = false;
bool main_btnStartSta = false;
GetPixmap *getPixmap;
QThread *thread;
QPixmap show_pix;
QPixmap save_pix;
};
#endif // MAINWINDOW_H
2. mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QMessageBox>
#include <QFile>
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
main_btnStartSta = true;
main_state = true;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::init()
{
ui->lb_vedio->setScaledContents(main_state);
this->setWindowTitle("Camera Client");
this->setWindowFlags(this->windowFlags()&~(Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint));
}
void MainWindow::on_btn_start_clicked()
{
QString name;
if ((main_btnStartSta = !main_btnStartSta) == false)
{
name = "Stop";
getPixmap = new GetPixmap;
thread = new QThread();
getPixmap->get_ipAddr = main_ipAddr;
getPixmap->get_port = main_port;
getPixmap->moveToThread(thread);
void (GetPixmap:: *sig_getOnePixmap)(QPixmap) = &GetPixmap::get_getOnePixmap;
void (MainWindow:: *slot_getOnePixmap)(QPixmap) = &MainWindow::main_getOnePixmap;
connect(getPixmap,sig_getOnePixmap,this,slot_getOnePixmap);
thread->start();
connect(thread,&QThread::started,getPixmap,&GetPixmap::run);
}
else
{
name = "Start";
thread->exit();
disconnect(getPixmap,SIGNAL(get_getOnePixmap(QPixmap)),this,NULL);
delete getPixmap;
}
ui->btn_start->setText(name);
}
void MainWindow::on_btn_screenshot_clicked()
{
save_pix = show_pix;
if (save_pix.isNull())
{
QMessageBox::information(this,tr("Info"),tr("There are no images to save."));
}
else
{
QString fileName = QFileDialog::getSaveFileName(this,tr("Save File"),QDir::homePath(),tr("jpegfile(*.jpg)"));
if (fileName.isEmpty())
{
QMessageBox::information(this,"Infor",tr("Save Cancel"));
return;
}
save_pix.save(fileName);
}
}
void MainWindow::on_btn_quit_clicked()
{
this->close();
}
void MainWindow::main_getOnePixmap(QPixmap pix)
{
show_pix = pix;
ui->lb_vedio->setPixmap(show_pix);
ui->lb_vedio->show();
}
4. 解析图像代码
1. getpixmap.h
#ifndef GETPIXMAP_H
#define GETPIXMAP_H
#include <QString>
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QByteArray>
#include <QPixmap>
class GetPixmap : public QObject
{
Q_OBJECT
public:
GetPixmap(QObject *parent = nullptr);
~GetPixmap();
public:
QString get_ipAddr;
QString get_port;
void run();
private slots:
void mjpeg_streamer_reply(QNetworkReply*);
signals:
void get_getOnePixmap(QPixmap);
private:
QNetworkAccessManager *manager;
QNetworkRequest *request;
};
#endif // GETPIXMAP_H
2. getpixmap.cpp
#include "getpixmap.h"
#include <QDebug>
GetPixmap::GetPixmap(QObject *parent) :
QObject(parent)
{
}
GetPixmap::~GetPixmap()
{
}
void GetPixmap::mjpeg_streamer_reply(QNetworkReply *reply)
{
QByteArray byteArr = reply->readAll();
QPixmap pix;
pix.loadFromData(byteArr);
emit get_getOnePixmap(pix);
manager->get(*request);
reply->deleteLater();
}
void GetPixmap::run()
{
QString url;
url.append("http://" + get_ipAddr + ":" + get_port + "/?action=snapshot");
qDebug() << url;
// qDebug() << "ipAddr:" << get_ipAddr;
// qDebug() << "port:" << get_port;
manager = new QNetworkAccessManager();
request = new QNetworkRequest(QUrl(url));
connect(manager,SIGNAL(finished(QNetworkReply*)), this, SLOT(mjpeg_streamer_reply(QNetworkReply*)));
manager->get(*request);
}
5. 效果展示
1. 三个界面
- 登录窗口
![Login界面]()
- 主界面
![MainWindow界面]()
- 视频效果
![视频效果]()
2. 说明
- 视频效果不卡顿,分辨率可以依靠mjpeg-streamer服务器运行时调整,CPU资源使用32M左右,在现在的树莓上,这点资源消耗,不值得一提
5. 打包源码,使用QT Creator 4.13编辑
上面提供的代码已经可以搭建出界面,和主要的内容了,下面是可以直接编译,还有不懂的同学可以下载,一下资源收费
链接:https://pan.baidu.com/s/1LWaKJxqcYcK6KHM2z6jgWg
提取码:ecci
复制这段内容后打开百度网盘手机App,操作更方便哦




浙公网安备 33010602011771号