Qt广告机客户端(下位机)
创始人
2024-05-29 22:57:11
0

目录

  • 功能
  • 结构
  • adClient.pro
  • main.cpp
  • adclient.h 客户端
  • adclient.cpp 客户端
    • addate.h 时间处理
    • addate.cpp 时间处理
    • adsocket.h 客户端Socket处理
    • adsocket.cpp 客户端Socket处理
    • weather.h 天气信息处理
    • weather.cpp 天气信息处理
    • rollmassege.h 滚动信息处理
    • rollmassege.cpp 滚动信息处理
  • 效果

功能

  1. 连接服务器(上位机)
  2. 广告图片播放模块
  3. 日期显示模块
  4. 天气显示模块
  5. 信息提示模块

结构

在这里插入图片描述

adClient.pro

QT       += core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11TARGET = adClient
TEMPLATE = appSOURCES += main.cpp\adclient.cpp \addate.cpp \adsocket.cpp \weather.cpp \rollmassege.cppHEADERS  += adclient.h \addate.h \adsocket.h \tcp_MSG.h \weather.h \rollmassege.hFORMS    += adclient.uiRESOURCES += \res.qrc

main.cpp

#include "adclient.h"
#include 
#include 
#include 
int main(int argc, char *argv[])
{QApplication a(argc, argv);// 判断当前运行环境是否为Linux或Windows。
#ifdef Q_OS_LINUXqDebug() << "Current OS is Linux";
#elif defined(Q_OS_WIN)qDebug() << "Current OS is Windows";
#elseqDebug() << "Unknown OS";
#endifQString folderName = "pic";//QString folderPath = QDir::currentPath() + "/" + folderName;QString folderPath = QApplication::applicationDirPath() + "/" + folderName;QDir folder(folderPath);if (!folder.exists()){bool success = folder.mkpath("."); // 创建文件夹if (success)qDebug() << "文件夹创建成功";elseqDebug() << "文件夹创建失败";}elseqDebug() << "文件夹已存在";QDir::setCurrent(folderPath);// 设置文件生成路径AdClient w;w.show();return a.exec();
}

adclient.h 客户端

#ifndef ADCLIENT_H
#define ADCLIENT_H#include 
#include "addate.h"
#include "adsocket.h"
#include "weather.h"
#include "rollmassege.h"
#include 
#include 
#include "stdlib.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include namespace Ui {
class AdClient;
}class AdClient : public QMainWindow
{Q_OBJECTpublic:explicit AdClient(QWidget *parent = 0);~AdClient();void saveFile();// 保存文件void InitStatusBar();// 初始化底部状态栏QString GetLocalIP();// 获取本地IPpublic slots:void showImage(QImage);// 图片显示void showProgressBar(int currentProgress,int finish);//进度条显示void autoPlayTimeOut();//自动播放void GUI_WarningMsg(QString title,QString text,QString buttons,QString defaultButton);//设置警报void connectToServer();// 链接到服务器
private:Ui::AdClient *ui;AdDate *date;AdSocket *socket;Weather *weater;RollMassege *rollmsg;QProgressDialog *progress;// 创建进度条QTimer autoPlayTimer;int index;QLabel *mLocalIP;QLabel *serverIP_lb;QLineEdit *serverIP;QLabel *serverPort_lb;QLineEdit *serverPort;QPushButton *connectTcp;};#endif // ADCLIENT_H

adclient.cpp 客户端

#include "adclient.h"
#include "ui_adclient.h"
#include QMap qMapPicturePath;// 图片路径//QTcpSocket 的默认缓存区大小是 64KB(65536字节)
AdClient::AdClient(QWidget *parent) :QMainWindow(parent),ui(new Ui::AdClient)
{ui->setupUi(this);this->setWindowIcon(QIcon(":/client.jpg"));date = new AdDate(ui->date_lb);//时间socket = new AdSocket;// TCP客户端weater = new Weather(ui->weather_lb);// 接收天气信息绘制rollmsg = new RollMassege(ui->msg_lb, ui->msg_lb);// 滚动信息connect(socket, SIGNAL(sig_showWeather(QString,QString,QString)), weater, SLOT(showWeather(QString,QString,QString)));connect(socket, SIGNAL(sig_showTxt(QString)), rollmsg, SLOT(showTxt(QString)));connect(socket, SIGNAL(sig_showImage(QImage)), this, SLOT(showImage(QImage)));connect(socket, SIGNAL(sig_showProgressBar(int,int)), this, SLOT(showProgressBar(int,int)),Qt::QueuedConnection);connect(socket, SIGNAL(GUI_WarningSignal(QString,QString,QString,QString)), this, SLOT(GUI_WarningMsg(QString,QString,QString,QString)));date->start();//更新时间progress = nullptr;autoPlayTimer.stop();connect(&autoPlayTimer, SIGNAL(timeout()), this, SLOT(autoPlayTimeOut()));InitStatusBar();// 初始化底部状态栏
}AdClient::~AdClient()
{delete socket;delete ui;
}// 保存文件
void AdClient::saveFile()
{QString fileName=qMapPicturePath.lastKey();qDebug()<<"lastKey:"<mLocalIP=new QLabel(this);mLocalIP->setMinimumWidth(230);QString ip = GetLocalIP();//    mLocalIP->setText("本地IP:"+ip);mLocalIP->setText("本地IP:"+tr("%1").arg(ip));serverIP_lb=new QLabel(this);serverIP_lb->setMinimumWidth(100);serverIP_lb->setText("服务器IP:");serverIP=new QLineEdit(this);serverIP->setMinimumWidth(200);serverIP->setInputMask("000.000.000.000");serverPort_lb=new QLabel(this);serverPort_lb->setMinimumWidth(60);serverPort_lb->setText("Port:");serverPort=new QLineEdit(this);serverPort->setMinimumWidth(60);serverPort->setPlaceholderText("8888");connectTcp=new QPushButton("链接",this);connectTcp->setMinimumWidth(100);ui->statusBar->addWidget(mLocalIP);ui->statusBar->addWidget(serverIP_lb);ui->statusBar->addWidget(serverIP);ui->statusBar->addWidget(serverPort_lb);ui->statusBar->addWidget(serverPort);ui->statusBar->addWidget(connectTcp);connect(connectTcp, SIGNAL(clicked()), this, SLOT(connectToServer()));
}// 获取本地IP
QString AdClient::GetLocalIP()
{QList list=QNetworkInterface::allAddresses();foreach(QHostAddress address,list){if(address.protocol()==QAbstractSocket::IPv4Protocol){qDebug()<qDebug()<<"显示图片"<<__LINE__;QPixmap pixmap=QPixmap::fromImage(image);// 内容是否自动缩放,参数true自动缩放ui->video_lb->setScaledContents(true);//显示图片的全部// 将图片缩放到指定大小,参数ui->label->size()表示缩放的大小,Qt::KeepAspectRatio表示保持图片的宽高比,Qt::SmoothTransformation表示使用平滑缩放算法ui->video_lb->setPixmap(pixmap.scaled(ui->video_lb->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));qDebug()<<"图片数量:"<=2){if(!autoPlayTimer.isActive()){// 两张以上图片开启播放autoPlayTimer.start(5000);index=0;}}else{autoPlayTimer.stop();}if(qMapPicturePath.count()>=1){// 功能没问题,调试注释,避免多次保存//saveFile();// 保存文件}
}//进度条显示
void AdClient::showProgressBar(int currentProgress, int finish)
{qDebug()<<"进度条显示"<<__LINE__;if (!progress){//创建进度条progress = new QProgressDialog("接收中....", "取消", 0, 100, this);progress->setWindowModality(Qt::WindowModal);progress->setFixedSize(this->width()*0.3,this->height()*0.3);progress->setVisible(true);}//usleep(500);//在Windows环境下已被弃用QThread::msleep(50);//休眠50毫秒//更新进度条progress->setValue(currentProgress * 100 / finish);//如果任务已经完成,隐藏进度条if (currentProgress == finish){qDebug()<<"进度条显示完成"<<__LINE__;progress->hide();delete progress;progress = nullptr;}
}//自动播放
void AdClient::autoPlayTimeOut()
{QList keyList = qMapPicturePath.keys();//存放的就是QMap的key值if(index>=qMapPicturePath.count())// 删除广告时有可能 >index=0;QImage image=qMapPicturePath.value(keyList.at(index));qDebug()<<"自动播放:"<Q_UNUSED(buttons)//忽略编译器发出的警告,表明变量event未使用Q_UNUSED(defaultButton)QMessageBox *box=new QMessageBox(QMessageBox::Warning,title,text,QMessageBox::Cancel,this);QTimer::singleShot(5000,this,[=](){if(!box->isHidden()&&box->isVisible()){box->accept();}});// 5s后必执行box->exec();return;
}// 链接到服务器
void AdClient::connectToServer()
{if(serverIP->text().isEmpty()||serverPort->text().isEmpty()){QMessageBox::warning(this,"提示","请输入IP或Port");return;}socket->id=GetLocalIP();socket->address=serverIP->text();qDebug()<<"服务器IP:"<address;socket->port=serverPort->text().toInt();qDebug()<<"服务器Port:"<port;qDebug()<<"是否已经连接:"<isValid();if(socket->isValid())// 如果套接字有效并且可以使用,则返回true;否则返回false。{socket->disconnectFromHost();// 与服务器断开连接// 无需再手动连接,只要更新IP和Port就行,AdSocket::conAgain会重新发起连接.}else{socket->connectToHost(QHostAddress(socket->address), socket->port);}qDebug()<<"是否已经连接:"<isValid();
}

addate.h 时间处理

#ifndef ADDATE_H
#define ADDATE_H#include 
#include 
#include 
#include class AdDate : public QObject
{Q_OBJECT
public:AdDate(QLabel *_mlabel, QObject *parent = 0);~AdDate();void start();// 定时器开启
public slots:void updateTime();// 定时器1s超时执行一次
private:QLabel *mlabel;QTimer *mtimer;
};#endif // ADDATE_H

addate.cpp 时间处理

#include "addate.h"AdDate::AdDate(QLabel *_mlabel, QObject *parent):QObject(parent)
{mlabel = _mlabel;mtimer = new QTimer;connect(mtimer, SIGNAL(timeout()), this, SLOT(updateTime()));
}AdDate::~AdDate()
{delete mtimer;
}void AdDate::start()
{mtimer->start(1000);
}void AdDate::updateTime()
{QString time = QTime::currentTime().toString("hh:mm:ss")+"\n"+QDate::currentDate().toString("yy/MM/dd ddd");mlabel->setText(time);
}

adsocket.h 客户端Socket处理

#ifndef ADSOCKET_H
#define ADSOCKET_H#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "string.h"
#include "tcp_MSG.h"class AdSocket : public QTcpSocket
{Q_OBJECT
public:explicit AdSocket(QObject *parent = 0);~AdSocket();QString id;QString address;int port;int readMsgType;signals:void sig_showWeather(QString city,QString area,QString wt);// 发送天气信息void sig_showTxt(QString tcp_Txt);// 发送文字信息void sig_showImage(QImage tcp_image);// 发送文字信息void sig_showProgressBar(int currentProgress, int finish);// 发送进度条信息void GUI_WarningSignal(QString title,QString text,QString buttons,QString defaultButton);//设置警报public slots:void readMsg();// 接收信息void conSuc(); // 成功建立连接void conAgain();// 重新连接void conAgain(QAbstractSocket::SocketError);// 重新连接private:int needFileSize;int currentReceiveSize;QByteArray currentReceiveByte;int milsec;QString fileName;
};#endif // ADSOCKET_H

adsocket.cpp 客户端Socket处理

#include "adsocket.h"
#include extern QMap qMapPicturePath;// 图片路径// QTcpSocket会自动处理大小端问题
AdSocket::AdSocket(QObject *parent) :QTcpSocket(parent)
{//注册tcp_MSG类型qRegisterMetaType("tcp_MSG");id = "0011";/* 每当有新的输入数据时,就会发出这个信号。请记住,新传入的数据只报告一次;如果您不读取所有数据,这个类会缓冲数据,您可以稍后读取它,但是除非新数据到达,否则不会发出信号。*/connect(this, SIGNAL(readyRead()),this, SLOT(readMsg()));//该信号在调用connectToHost()并成功建立连接之后发出。connect(this, SIGNAL(connected()),this, SLOT(conSuc()));// 该信号在套接字断开连接时发出connect(this, SIGNAL(disconnected()),this, SLOT(conAgain()));address="127.0.0.1";port=8888;//connectToHost(QHostAddress(address), port);// 默认连接127.0.0.1 8888//该信号在错误发生后发出。socketError参数描述发生错误的类型connect(this, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(conAgain(QAbstractSocket::SocketError)));readMsgType=MsgType::Init;milsec=0;
}AdSocket::~AdSocket()
{}// 接收信息
void AdSocket::readMsg()
{//读取缓冲区数据QByteArray  buffer = readAll();qDebug()<<"进来了"<<__LINE__;if(readMsgType==MsgType::Init){tcp_MSG *msg=(tcp_MSG *)buffer.data();        //强转为结构体,需要用结构体指针接收qDebug()<<"进来了"<<__LINE__;qDebug()<<"类型"<type;switch (msg->type){case WEATHER://天气{QString city=msg->city;QString area=msg->area;QString weather=msg->weather;//weather="\t\t"+city+"\t"+area+"\n"+weather;emit sig_showWeather(city,area,weather);// 发送天气信息break;}case MASSEGE:// 留言{QString tcp_Txt=msg->txt;qDebug()<<"文字信息:"<qDebug()<<"添加广告"<<__LINE__;qDebug()<<"文件名"<< QString(msg->fileName);qDebug()<<"编号"<< msg->index;qDebug()<<"总数"<< msg->allAd_Num;needFileSize=msg->fileSize;currentReceiveSize=0;currentReceiveByte.clear();QByteArray  sendTcpData;//使用字节数组,将结构体转为字符数组,发送的是字符数组(数据在传输过程中都是byte类型的)//直接sizeof(senddata)内存会变小,设置了对齐方式解决sendTcpData.resize(sizeof(tcp_backMSG));tcp_backMSG backMsg={};strcpy(backMsg.id,id.toUtf8().data());backMsg.state=1;backMsg.type=MsgType::Write_back;//将封装好的结构体转为QByteArray数组,因为传输都是Byte类型memcpy(sendTcpData.data(),&backMsg,sizeof(tcp_backMSG));this->write(sendTcpData);// 回复fileName.clear();fileName=QString(msg->fileName);readMsgType=MsgType::AD_add;break;}case AD_delete://删除广告{qDebug()<<"删除广告"<<__LINE__;qDebug()<<"文件名"<< QString(msg->fileName);int  success= qMapPicturePath.remove(QString(msg->fileName));if(success){if(qMapPicturePath.count()>=1){// 有图片emit sig_showImage(qMapPicturePath.first());}else{// 没有图片QImage image(100, 100, QImage::Format_RGBA8888);image.fill(QColor(0, 0, 0, 0));// 纯透明图片emit sig_showImage(image);}emit GUI_WarningSignal("提示","删除广告成功",NULL,NULL);}else{emit GUI_WarningSignal("提示","删除广告失败",NULL,NULL);}break;}default:qDebug()<<"";break;}}else if(readMsgType==MsgType::AD_add){qDebug()<<"添加广告"<<__LINE__;qDebug()<<"需要接收大小:"<qDebug()<<"图片接收完成";startTime = QTime::currentTime();QByteArray Ret_bytearray = QByteArray::fromBase64(currentReceiveByte);QBuffer buffer(&Ret_bytearray);buffer.open(QIODevice::WriteOnly);QPixmap imageresult;imageresult.loadFromData(Ret_bytearray);qMapPicturePath.insert(fileName,imageresult.toImage());// 先插入键值emit sig_showImage(imageresult.toImage());readMsgType=MsgType::Init;endTime = QTime::currentTime();milsec += startTime.msecsTo(endTime);qDebug()<<"接收消耗时间"<QByteArray  sendTcpData;//使用字节数组,将结构体转为字符数组,发送的是字符数组(数据在传输过程中都是byte类型的)//直接sizeof(senddata)内存会变小,设置了对齐方式解决sendTcpData.resize(sizeof(tcp_backMSG));tcp_backMSG msg={};strcpy(msg.id,id.toUtf8().data());msg.state=0;msg.type=MsgType::Init;//将封装好的结构体转为QByteArray数组,因为传输都是Byte类型memcpy(sendTcpData.data(),&msg,sizeof(tcp_backMSG));this->write(sendTcpData);qDebug()<<"connect success";
}// 重新连接
void AdSocket::conAgain()
{qDebug()<<"套接字断开连接时重新连接";abort();// 终止当前连接并重置套接字connectToHost(QHostAddress(address), port);
}
// 重新连接
void AdSocket::conAgain(QAbstractSocket::SocketError error)
{qDebug()<<"连接失败:"<connectToHost(QHostAddress(address), port);}
}

weather.h 天气信息处理

#ifndef WEATHER_H
#define WEATHER_H#include 
#include 
#include 
class Weather : public QObject
{Q_OBJECT
public:explicit Weather( QLabel *_label,QObject *parent = 0);signals:public slots:void showWeather(QString city,QString area,QString weather);private:QLabel *label;QString _city;QString _area;
};#endif // WEATHER_H

weather.cpp 天气信息处理

#include "weather.h"Weather::Weather( QLabel *_label, QObject *parent) :QObject(parent)
{label = _label;
}void Weather::showWeather(QString city,QString area,QString weather)
{_city=city;qDebug()<<"城市:"<<_city;_area=area;qDebug()<<"地区:"<<_area;weather="\t\t"+_city+"\t"+_area+"\n\t"+weather;label->setText(weather);
}

rollmassege.h 滚动信息处理

#ifndef ROLLMASSEGE_H
#define ROLLMASSEGE_H#include 
#include 
#include 
#include 
#include 
#include class RollMassege : public QLabel
{Q_OBJECT
public:explicit RollMassege(QWidget *parent = 0);explicit RollMassege(QLabel *_label, QWidget *parent = 0);void paintEvent(QPaintEvent *event);
signals:public slots:void updateMsg();void showTxt(QString tcp_Txt);
private:QString txt;QRect rect;int offset;//偏移量QTimer *timer;
};#endif // ROLLMASSEGE_H

rollmassege.cpp 滚动信息处理

#include "rollmassege.h"
#include RollMassege::RollMassege(QWidget *parent) :QLabel(parent)
{
}RollMassege::RollMassege(QLabel *_label, QWidget *parent) :QLabel(parent)
{rect = _label->geometry();rect.setWidth(798);rect.setHeight(80);setGeometry(rect);show();qDebug()<start(50);
}
// 绘画事件
void RollMassege::paintEvent(QPaintEvent *event)
{Q_UNUSED(event); //忽略编译器发出的警告,表明变量event未使用QPainter painter(this);QFont font;font.setPointSize(16);painter.setFont(font);painter.drawText(rect.x()+offset, rect.y()+30, txt);// 绘制文字,x+偏移量
}void RollMassege::updateMsg()
{offset--;if(offset<0) offset = rect.width();update();// 刷新,触发绘画事件paintEvent
}void RollMassege::showTxt(QString tcp_Txt)
{txt =tcp_Txt;update();
}

效果

在这里插入图片描述
在这里插入图片描述

相关内容

热门资讯

一持有型不动产ABS获批通过 根据上交所网站信息,太保资产-世纪互联数据中心持有型不动产资产支持专项计划获批通过,这是市场通过的第...
美国称其从沙特获得6000亿美... 据报道,美国称其从沙特获得6000亿美元投资。
长三角生态绿色一体化发展示范区... 中新网嘉兴5月13日电(记者 王逸飞)13日,在浙江嘉善举行的2025年国际生物多样性日长三角生态绿...
沙特人工智能公司HUMAIN将... 5月13日,沙特公共投资基金旗下人工智能公司HUMAIN宣布同英伟达建立战略合作伙伴关系。两家公司将...
科技可以如此有温度,多款高科技... 转自:上观新闻外骨骼康复训练器、手语AI主持人……科技助残有了具象。今天下午,以“融合无界 科技无限...
万集科技深耕激光和智能网联方向... 上证报中国证券网讯 5月13日晚,万集科技披露公告,万集科技及下属武汉万集、深圳万集于2025年4月...
官宣!中方调整对美关税 为落实中美经贸高层会谈的重要共识,根据《中华人民共和国关税法》、《中华人民共和国海关法》、《中华人民...
从“小家”到“万家”:闽台夫妻... 中新社福州5月13日电 题:从“小家”到“万家”:闽台夫妻的大陆家装创业路  作者 郑江洛  在福州...
俄副外长:俄美两国将举行双边谈... △俄罗斯副外长里亚布科夫(资料图)当地时间13日,俄罗斯外交部副部长里亚布科夫表示,俄美两国将举行双...
“应急使命·2025”——台风... 中新网南宁5月13日电(林浩 王以照)为提升防范化解重大安全风险和应对突发事件的能力,5月13日,应...
中国国家能源局主要负责人会见洪... 中新社北京5月13日电 (王梦瑶)据中国国家能源局消息,国家能源局局长王宏志日前在北京会见洪都拉斯能...
应对AI对科研诚信的挑战,高校... 转自:中国科学报当前,人工智能(AI)对高校的影响是全面且深入的,这已成为高教界的共识。不过,这种影...
贝莱德CEO:市场在找到新平衡...   尽管中美达成贸易休战协议,但全球金融业一些知名领军者仍在提防市场可能出现的持续波动。不过他们也表...
中方调整对美关税:由34%调整... 国务院关税税则委员会5月13日发布公告称,为落实中美经贸高层会谈的重要共识,根据《中华人民共和国关税...
来伊份再回应:与消费者达成和解 5月13日,来伊份发布关于消费者反映蜜枣粽问题处理的情况说明:事情发生后,公司迅速采取行动,对相关批...
4月份黑龙江省居民消费价格同比... 转自:黑龙江新闻网近日,记者从国家统计局黑龙江调查总队获悉,2025年4月份,黑龙江省消费市场运行总...
同有科技:股东及副总经理拟合计... 格隆汇5月13日|同有科技晚间公告,持股8.38%的股东杨永松计划以集中竞价方式减持公司股份不超过4...
钜泉科技2024年股权激励计划... 上证报中国证券网讯钜泉科技5月13日晚发布公告,公司于近日收到中国证券登记结算有限责任公司上海分公司...
AI热评:百万网红被立案是自导... 转自:法治日报 #律师称网红自导自演自杀已涉嫌违法#【A...
挖地三尺,诱人羊毛来了 图:Isabelle Feliu上次写了支付宝、微信羊毛。点击重温我还担心,知道的人已经很多、没啥参...