QT局域网监控系统

Posted 狗蛋儿l

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QT局域网监控系统相关的知识,希望对你有一定的参考价值。

客户端ui:

头文件:

#ifndef MYWIN_H
#define MYWIN_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
class MyWin;
}

class MyWin : public QWidget
{
    Q_OBJECT

public:
    explicit MyWin(QWidget *parent = 0);
    ~MyWin();
    void paintEvent(QPaintEvent *e);

private slots:
    void on_bnt_connect_clicked();
    void disconnect_slot();
    void read_data();

private:
    Ui::MyWin *ui;
    QTcpSocket *socket;

    char *data;
    int  len; //图像大小
    int  len_rcv; //接收大小
};

#endif // MYWIN_H

主文件:

#include "mywin.h"
#include <QApplication>
#include <QWidget>

#define W  360
#define H  380

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget wid;

    MyWin w(&wid), w2(&wid), w3(&wid), w4(&wid);

    w.setGeometry(0, 0, W, H);
    w2.setGeometry(W, 0, W, H);
    w3.setGeometry(0, H, W, H);
    w4.setGeometry(W, H, W, H);

    wid.show();
    return a.exec();
}

窗口文件:

#include "mywin.h"
#include "ui_mywin.h"
#include <QMessageBox>
#include <QDebug>
#include <QPainter>

#define LEN 3*1024*1024
#define P_LEN 1380

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

    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnect_slot()));
    connect(socket, SIGNAL(readyRead()), this, SLOT(read_data()));
    data = new char[LEN];

}

MyWin::~MyWin()
{
    delete ui;
    delete [] data;
    delete socket;
}

void MyWin::paintEvent(QPaintEvent *e)
{
    QPixmap map;

    if ((len_rcv >= len) && (len > 0))
    {
        map.loadFromData((uchar *)data, len);

        QPainter p(this);
        p.drawPixmap(10, 80, 320, 240, map);
        socket->write("new_request");
        len_rcv = 0;
    }

}

void MyWin::read_data()
{
    int ret;

    ret = socket->read(data+len_rcv, P_LEN);
    if (0 == strncmp("newImage", data+len_rcv, 8))
    {
        len = atoi(data+len_rcv+9);
//        qDebug() << len;
    }
    else
    {
        len_rcv += ret;
        if (len_rcv >= len)
        {
            update();
            return;
        }
    }


    socket->write("ack");
}

void MyWin::disconnect_slot()
{
    ui->bnt_connect->setEnabled(true);
}

void MyWin::on_bnt_connect_clicked()
{
    QString ip = ui->lnd_ip->text();

    socket->connectToHost(ip, 12345);
    if (!socket->waitForConnected(1000))
    {
        QMessageBox::critical(this, "error", "server connection failed");
        return;
    }

    len_rcv = 0;
    socket->write("new_request");
    ui->bnt_connect->setEnabled(false);
}

服务端ui:

头文件:

#ifndef MYWIN_H
#define MYWIN_H

#include <QWidget>
#include <QCamera>
#include <QCameraViewfinder>
#include <QTcpServer>
#include <QTcpSocket>
#include <QList>
#include <QTimer>

namespace Ui {
class MyWin;
}

class MyWin : public QWidget
{
    Q_OBJECT

public:
    explicit MyWin(QWidget *parent = 0);
    ~MyWin();

private slots:
    void new_client();
    void distconnect_client();
    void read_data();
    void timer_slot();

private:
    Ui::MyWin *ui;

    QCamera *cam;
    QCameraViewfinder *view;

    QTcpServer *server;
    QList<QTcpSocket *> clients;
    QTimer *timer;
};

#endif // MYWIN_H

主文件:

#include "mywin.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyWin w;
    w.show();

    return a.exec();
}

窗口文件:

#include "mywin.h"
#include "ui_mywin.h"
#include <QMessageBox>
#include <QScreen>
#include <QBuffer>

#define W  640
#define H  480

#define LEN  (W*H*2)

#define P_LEN  1380

class Data {
public:
    char data[LEN]; //图像数据
    int  len; //图像大小
    int  len_sent; //已发出的数据长度
    int  stats; //工作状态, 0表示空闲(图像数据可以更新), 1表示图像数据传输中(还不可以更新图像数据), 2表示需要发出图像数据的第一部分
    Data() {
        len_sent = 0;
        stats = 0;
    }
};

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

    server = new QTcpServer(this);
    if (!server->listen(QHostAddress::Any, 12345))
    {
        QMessageBox::critical(this, "error", "listen port failed");
        exit(0);
    }

    connect(server, SIGNAL(newConnection()), this, SLOT(new_client()));

    cam = new QCamera;
    view = new QCameraViewfinder(this);
    view->setGeometry(0, 0, W, H);
    view->show();

    cam->setViewfinder(view);
    cam->start();

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timer_slot()));
    timer->start(100);

    resize(640, 600);
}

MyWin::~MyWin()
{
    delete ui;
    cam->stop();
    delete cam;
    delete view;
    delete server;
}

void MyWin::timer_slot()
{
    QString s("newImage:%1");
    QScreen *screen = QApplication::primaryScreen();
    QPixmap map = screen->grabWindow(view->winId()); //只截view窗口对象上的图像,也就是摄像头的数据

   //再编码成jpg图像
    QByteArray ba;
    QBuffer    bf(&ba);
    map.save(&bf, "jpg", 50);



    //给每个QTcpSocket对象更新图像数据
    for (int i = 0; i < clients.size(); i++)
    {
        Data *d = (Data*)clients.at(i)->userData(0);

        if (d->stats != 1) // 1表示传输中
        {
            memcpy(d->data, ba.data(), ba.size());
            d->len = ba.size();

            if (d->stats == 2)
            {
                d->stats = 1; //改为传输中的状态
                d->len_sent = 0;
                clients.at(i)->write(s.arg(d->len).toUtf8());
            }
        }
    }
}

void MyWin::read_data()
{
    QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());
    QString str = client->readAll();
    Data *d = (Data*)client->userData(0);
    QString s("newImage:%1");

    if (str == "new_request")
    {
        if ((d->len) && (d->stats==0)) //图像大小不为0,表示已更新图像数据了
        {
            d->stats = 1;
            client->write(s.arg(d->len).toUtf8());
            d->len_sent = 0;
        }
        else //图像数据还没有更新
            d->stats = 2; //在定时器的槽函数里发出"newImage..."
    }
    if (str == "ack")
    {
        int len_send = P_LEN;
        if (d->len_sent >= d->len) //如果图像已传输完毕
            return;

        if ((d->len_sent + P_LEN) > d->len)
            len_send = d->len - d->len_sent;

        d->len_sent += client->write(d->data+d->len_sent, len_send);
        if (d->len_sent >= d->len)
        {
            d->stats = 0; //传输完毕后,把状态改为可更新
            d->len = 0;
        }
    }

}

void MyWin::distconnect_client()
{
    QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());
    Data *d = (Data*)client->userData(0);

    clients.removeOne(client);
}

void MyWin::new_client()
{
    QTcpSocket *client = server->nextPendingConnection();

    connect(client, SIGNAL(disconnected()), this, SLOT(distconnect_client()));
    connect(client, SIGNAL(readyRead()), this, SLOT(read_data()));
    client->setUserData(0, (QObjectUserData *)new Data);
    clients.append(client);
}

码云

以上是关于QT局域网监控系统的主要内容,如果未能解决你的问题,请参考以下文章

26.Qt Quick QML-RotationAnimationPathAnimationSmoothedAnimationBehaviorPauseAnimationSequential(代码片段

Qt 5.8 QTcpServer 无法监听局域网 ip 地址问题

Qt5 从局域网获取 mjpeg 流

Qt调用系统DLL,判断网络连接状态

Qt使用QAudioInputQAudioOutput实现局域网的音频通话

Qt、QNetworkAccess Manager下载大文件频繁失败