Small chat software based on C++/qml (including source code)
2022/1/19 1:04:35
本文主要是介绍Small chat software based on C++/qml (including source code),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
https://www.programmersought.com/article/74196226714/
Server source code
main.qml
import QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import Server_support 1.0
Window{
id:window
width:800
height:550
Rectangle{
width:800
height:550
gradient: Gradient {//Gradient attribute
GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
position: 0.0; color: "white"
}
GradientStop{
position: 1.0; color: "pink"
}
}
}
visible:true
ListView{
add: Transition {
//Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
}
id:listview
anchors.top: parent.top
anchors.bottom: bottomrect.top
anchors.left:parent.left
anchors.right:parent.right
//anchors' object is either a sibling node (provide id)
//Either the child node (parent)
delegate:Component{ //here delegate: must be followed by Component
Rectangle{
width:550
height:label1.height+20
opacity: 0.8
// color:"black"
BorderImage{
//Chat bubble
id:qipao
source:"pao.png"
width:label1.width+30
height:label1.height<=30?30:label1.height+5
// width:20
border.left: 10
border.right: 10
border.top:10
border.bottom:10
x:parent.width-width
Text{
id:label1
/*************
Here is the focus of the variable size chat bubble
According to the length of the obtained value and the pixels occupied by each word
*************/
width:label1.text.length<=10?label1.text.length*12:120
font.pixelSize: 12
anchors.centerIn:parent
anchors.leftMargin:10
wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
text:detail
}
}
}
}
model:ListModel{
id:listmodel
ListElement{
detail:"This is Server."
}
}
}
//Right
Rectangle {
id:message3
border.color: "black"
anchors.right: parent.right
anchors.top: window.top
height:510
width:window.width*0.3
gradient: Gradient {//Gradient attribute
GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
position: 0.0; color: "red"
}
GradientStop{
position: 1.0; color: "blue"
}
}
}
Label{
id:label2;
text:"value";
anchors.top: message3.top
x:570
}
//Bottom
Rectangle{
height: 40
width: 550
anchors.bottom: parent.bottom
id:bottomrect
Row{
TextField{
id:textfield
placeholderText: "input content"
height:bottomrect.height
width:window.width*0.7
}
}
Button{
id:button1
text:"Send"
x:560
anchors.top: message3.bottom
onClicked: {
listmodel.append({"detail":textfield.text})
var result = textfield.text
server.sendMessage(result);
//textfield.text='' Clear the input box after sending the message
}
}
Button
{
id:button2
text:"Connect"
anchors.left: button1.right
onClicked:
{
label2.text=server.mystring
server.connect_client();
}
//Connect the signal to qml
Connections{
target:server;
onMystringChanged:label2.text = str;
}
}
Button
{
id:button3
text:"Quit"
anchors.left: button2.right
onClicked:
{
window.close();
}
}
}
Server
{
id:server
}
//Receive the message on the left
// Label{
// id:recv_message_window;
// text:"recv_message";
// width:275
// height:550
// y:20
// Button
// {
// id:button4
// text:"recvmsg"
// x:750
// y:490
// //anchors.right: window.right
// onClicked:
// {
// recv_message_window.text=server.message
// }
// Connections{
// target:server;
// onMessageChanged: recv_message_window.text = str;
// }
// }
// }
ListView{
width:200
height:550
add: Transition {
//Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
}
id:listview2
anchors.top: parent.top
anchors.bottom: bottomrect.top
anchors.left:parent.left
anchors.right:parent.right
//anchors' object is either a sibling node (provide id)
//Either the child node (parent)
delegate:Component{ //here delegate: must be followed by Component
Rectangle{
width:200
height:label3.height
opacity: 0.8
BorderImage{
//Chat bubble
id:qipao
source:"pao.png"
width:label3.width+30
height:label3.height<=30?30:label3.height+5
// width:20
border.left: 10
border.right: 10
border.top:10
border.bottom:10
x:parent.width-width
Text{
id:label3
/*************
Here is the focus of the variable size chat bubble
According to the length of the obtained value and the pixels occupied by each word
*************/
width:label3.text.length<=10?label3.text.length*12:120
font.pixelSize: 12
anchors.centerIn:parent
anchors.leftMargin:10
wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
text:detail
}
}
}
}
model:ListModel{
id:listmodel2
ListElement{
detail:""
}
}
}
Rectangle{
anchors.top: parent.top
id:bottomrect2
Row{
Text{
id:textfield2
height:bottomrect2.height
width:window.width*0.7
// anchors.top : ListView.top
}
}
}
Button
{
id:button4
text:"recvmsg"
x:720
y:510
anchors.left: button3.right
onClicked:
{
listmodel2.append({"detail":textfield2.text})
textfield2.text=server.message
}
Connections{
target:server;
onMessageChanged: textfield2.text = str;
}
}
}
server.cpp
#include "server.h"
static SOCKET slisten;
static SOCKET sClient;
Server::Server(QObject *parent):QObject(parent)
{
m_pstring = new QString;
recv_data = new QString;
send_data = new QString;
}
Server::~Server()
{
delete this->m_pstring;
}
QString Server::getString()
{
setString("waiting connect...");
return *(this->m_pstring);
}
void Server::setString(QString string){
*(this->m_pstring)=string;
emit mystringChanged(string);//Send signal
}
QString Server::message()
{
return *recv_data;
}
void Server::setMessage(QString string)
{
*recv_data=string;
}
void Server::sendMessage(QString string)
{
*send_data = string;
qDebug()<<*send_data;
}
void Server::connect_client()
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(sockVersion, &wsaData) != 0)
{
exit(0);
}
slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
cout<<"socket error !"<<endl;
exit(0);
}
else
cout<<"socket suceess."<<endl;
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8080);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
cout << "bind error !" << endl;
}
else
cout<<"bind success."<<endl;
if (listen(slisten, 5) == SOCKET_ERROR)
{
cout << "listen error !"<< endl;
exit(0);
}
else
cout<<"listen succeed."<<endl;
start_thread1();
}
void Server::recvsend_message()
{
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
int count=0;
start_thread2();
while(true)
{
count++;
if(count==1)
{
cout<<"wating connect..."<<endl;
}
sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
if(count==1)
{
cout<<"accept one client."<<endl;
}
if (sClient == INVALID_SOCKET)
{
printf("accept error !");
continue;
}
if(count == 1)
{
cout <<"accepted a connection:"<< inet_ntoa(remoteAddr.sin_addr) << endl;
}
cout << inet_ntoa(remoteAddr.sin_addr)<<":";
send_news();
}
closesocket(sClient);
WSACleanup();
}
void Server::recv_news()
{
char revData[255];
int ret = 0;
int count = 0;
while(true)
{
ret = recv(sClient, revData, 255, 0);
count++;
if(count == 1)
{
cout<<"recv success!"<<endl;
}
if (ret > 0)
{
revData[ret] = '\0';
*recv_data = QString(QLatin1String(revData));
qDebug()<<*recv_data;
emit messageChanged(*recv_data);
cout<<"recv a massgae:"<<revData<<endl;
}
}
}
void Server::send_news()
{
char sendbuffer[255];
while(true)
{
if((*send_data).size() > 0)
{
QByteArray buffer = (*send_data).toUtf8();
char *sendData = buffer.data();
strcpy(sendbuffer,sendData);
sendbuffer[strlen(sendbuffer)]='\0';
cout<<sendbuffer<<endl;
send(sClient, sendbuffer, strlen(sendbuffer), 0);
*send_data = "\0";
memset(sendbuffer,0,255);
}
}
}
void Server::start_thread1()
{
std::thread t1(&Server::thread1,this);
t1.detach();
}
void* Server::thread1(void *this_)
{
Server *_this = (Server*) this_;
_this->recvsend_message();
return _this;
}
void Server::start_thread2()
{
std::thread t2(&Server::thread2,this);
t2.detach();
}
void* Server::thread2(void *this_)
{
Server *_this = (Server*) this_;
_this->recv_news();
return _this;
}
void Server::start_thread3()
{
std::thread t3(&Server::thread3,this);
t3.detach();
}
void* Server::thread3(void *this_)
{
Server *_this = (Server*) this_;
_this->send_news();
return _this;
}
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include<QString>
#include<qdebug.h>
#include<iostream>
#include<windows.h>
#include<thread>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
class Server : public QObject
{
Q_OBJECT
//Exposed to QML attributes
Q_PROPERTY(QString mystring READ getString WRITE setString NOTIFY mystringChanged)
Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
explicit Server(QObject *parent = 0);
Q_INVOKABLE QString getString(); //Q_INVOCABLE is exposed to QML
Q_INVOKABLE void setString(QString string);
Q_INVOKABLE QString message();
Q_INVOKABLE void setMessage(QString string);
Q_INVOKABLE void sendMessage(QString string);
~Server();
Q_INVOKABLE void connect_client();
void recvsend_message();
void recv_news();
void send_news();
void start_thread1();
void start_thread2();
void start_thread3();
static void* thread1(void* this_);
static void* thread2(void* this_);
static void* thread3(void* this_);
signals:
void mystringChanged(QString value); //signal
void messageChanged(QString str);
public:
QString *m_pstring;
QString *recv_data;
QString *send_data;
};
#endif // SERVER_H
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include<QtQml>
#include"server.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
//Register to QML
qmlRegisterType<Server>("Server_support",1,0,"Server");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Client source code
main.qml
import QtQuick 2.4
import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import RegisterClient 1.0
Window{
id:window
width:800
height:550
Rectangle{
width:800
height:550
gradient: Gradient {//Gradient attribute
GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right.
position: 0.0; color: "white"
}
GradientStop{
position: 1.0; color: "pink"
}
}
}
visible:true
ListView{
add: Transition {
//Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
}
id:listview
anchors.top: parent.top
anchors.bottom: bottomrect.top
anchors.left:parent.left
anchors.right:parent.right
//anchors' object is either a sibling node (provide id)
//Either the child node (parent)
delegate:Component{ //here delegate: must be followed by Component
Rectangle{
width:550
height:label1.height+20
opacity: 0.8
// color:"black"
BorderImage{
//Chat bubble
id:qipao
source:"pao.png"
width:label1.width+30
height:label1.height<=30?30:label1.height+5
// width:20
border.left: 10
border.right: 10
border.top:10
border.bottom:10
x:parent.width-width
Text{
id:label1
/*************
Here is the focus of the variable size chat bubble
According to the length of the acquired value and the pixels occupied by each word
*************/
width:label1.text.length<=10?label1.text.length*12:120
font.pixelSize: 12
anchors.centerIn:parent
anchors.leftMargin:10
wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
text:detail
}
}
}
}
model:ListModel{
id:listmodel
ListElement{
detail:"This is Client."
}
}
}
//Right
Rectangle {
id:message3
border.color: "black"
anchors.right: parent.right
anchors.top: window.top
height:510
width:window.width*0.3
gradient: Gradient {//Gradient attribute
GradientStop{//The color gradient from top to bottom, you need to use the attribute rotation to set 90 from the right
position: 0.0; color: "red"
}
GradientStop{
position: 1.0; color: "blue"
}
}
}
Label{
id:label2;
text:"value";
anchors.top: message3.top
x:570
}
//Bottom
Rectangle{
height: 40
width: 550
anchors.bottom: parent.bottom
id:bottomrect
Row{
TextField{
id:textfield
placeholderText: "input content"
height:bottomrect.height
width:window.width*0.7
}
}
Button{
id:button1
text:"Send"
x:560
anchors.top: message3.bottom
onClicked: {
listmodel.append({"detail":textfield.text})
client.obtain_message(textfield.text);
//textfield.text=''
}
}
Client
{
id:client
}
Button
{
id:button2
text:"Connect"
anchors.left: button1.right
onClicked:
{
label2.text=client.mystring
client.connect_server();
//client.communication();
}
//Connect the signal to qml
Connections{
target:client;
onMystringChanged:label2.text = str;
//The value here is the parameter in the signal function
}
}
Button
{
id:button3
text:"Quit"
anchors.left: button2.right
onClicked:
{
window.close();
}
}
}
ListView{
width:200
height:550
add: Transition {
//Set the animation when adding Item from 100, 100 to is not set, it is the default in ListView
NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
}
id:listview2
anchors.top: parent.top
anchors.bottom: bottomrect.top
anchors.left:parent.left
anchors.right:parent.right
//anchors' object is either a sibling node (provide id)
//Either the child node (parent)
delegate:Component{ //here delegate: must be followed by Component
Rectangle{
width:200
height:label3.height
opacity: 0.8
BorderImage{
//Chat bubble
id:qipao
source:"pao.png"
width:label3.width+30
height:label3.height<=30?30:label3.height+5
// width:20
border.left: 10
border.right: 10
border.top:10
border.bottom:10
x:parent.width-width
Text{
id:label3
/*************
Here is the focus of the variable size chat bubble
According to the length of the obtained value and the pixels occupied by each word
*************/
width:label3.text.length<=10?label3.text.length*12:120
font.pixelSize: 12
anchors.centerIn:parent
anchors.leftMargin:10
wrapMode: Text.Wrap //Multi-line text will wrap automatically if it exceeds the width
text:detail
}
}
}
}
model:ListModel{
id:listmodel2
ListElement{
detail:""
}
}
}
Rectangle{
anchors.top: parent.top
id:bottomrect2
Row{
Text{
id:textfield2
height:bottomrect2.height
width:window.width*0.7
// anchors.top : ListView.top
}
}
}
Button
{
id:button4
text:"recvmsg"
x:720
y:510
anchors.left: button3.right
onClicked:
{
listmodel2.append({"detail":textfield2.text})
textfield2.text=client.message
}
Connections{
target:client;
onMessageChanged: textfield2.text = str;
}
}
}
/*
Window {
width:200
height: 100
visible: true
Button{
id:btn1;
height:20;
width:60;
text:"button";
onClicked: {
//qml operation c++
//btn1.text=myobj.mystring;
label1.text = myobj.mystring;
}
}
Label{
id:label1;
text: "Initial value";
anchors.left:btn1.right;
//Create an object anchors.leftMargin: 12;
}
MyClassType
{
id:myobj;
}
//Connect the signal to qml
Connections{
target:myobj;
onMystringChanged:label1.text=value;
//The value here is the parameter in the signal function
}
}*/
client.cpp
#include"client.h"
static SOCKET sclient;
client::client(QObject *parent)
:QObject(parent)
{
this->m_pstring = new QString;
this->send_data = new QString;
this->recv_data = new QString;
}
client::~client()
{
delete this->m_pstring;
delete this->send_data;
delete this->recv_data;
}
QString client::get_send_data()
{
return *recv_data;
}
QString client::getString()
{
setString("connect succeed...");
return *(this->m_pstring);
}
void client::setString(QString string)
{
*(this->m_pstring)=string;
emit mystringChanged(string);//Send signal
}
void client::setMessage(QString string)
{
*recv_data=string;
}
void client::sendMessage(QString string)
{
*send_data = string;
qDebug()<<*send_data;
}
void client::obtain_message(QString string)
{
*send_data = string;
qDebug()<<*send_data;
}
void client::connect_server()
{
WORD sockVersion = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(sockVersion, &data) != 0)
{
exit(0);
}
sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
printf("invalid socket!");
exit(0);
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8080);
serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (::connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
printf("connect error !");
closesocket(sclient);
exit(0);
}
cout<<"connect succeed..."<<endl;
start_thread1();
}
void client::communication()
{
/*
Create a separate thread for recv outside the loop
Send messages in a loop
*/
start_thread2();
char sendData[255];
while(true)
{
//cout<<"sendmessage:";
// cout<<"!!!!!!!!!!!!!!!!!!!!!!"<<endl;
if( (*send_data).size() > 0)
{
QByteArray buffer =(*send_data).toUtf8();
char *p =buffer.data();
strcpy(sendData,p);
sendData[strlen(sendData)]='\0';
cout<<sendData<<endl;
send(sclient, sendData, strlen(sendData), 0);
*send_data = "\0";
memset(sendData,0,strlen(sendData));
}
}
closesocket(sclient);
WSACleanup();
}
QString client::message()
{
return *recv_data;
}
void client::recv_news()
{
char recData[255];
int ret = 0;
int count = 0;
while(true)
{
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
ret = recv(sclient, recData, 255, 0);
count++;
if(count == 1)
{
cout<<"recv success!"<<endl;
}
if (ret>0)
{
recData[ret] = '\0';
cout<<"recv a messgae:"<<recData<<endl;
*recv_data = QString(QLatin1String(recData));
emit messageChanged(*recv_data);
}
*recv_data="\0";
memset(recData,0,255);
}
}
void client::send_news()
{
char sendData[255];
//char sendData[]="This client ,hello server";
//cout<<"!!!!!!!!!!!!!!!!!!!!!!"<<endl;
if((*send_data).size() > 0)
{
QByteArray buffer =(*send_data).toUtf8();
char *p =buffer.data();
strcpy(sendData,p);
sendData[strlen(sendData)]='\0';
cout<<sendData<<endl;
send(sclient, sendData, strlen(sendData), 0);
//cout<<"Now,send the message to server."<<endl;
*send_data = '\0';
memset(sendData,0,strlen(sendData));
}
}
void client::start_thread1()
{
cout<<"start communicate."<<endl;
std::thread t(&client::thread1,this);
t.detach();
}
void* client::thread1(void* _this)
{
client* p = (client*) _this;
p->communication();
return p;
}
void client::start_thread2()
{
std::thread t(&client::thread2,this);
t.detach();
}
void* client::thread2(void* _this)
{
client*p = (client*) _this;
p->recv_news();
return p;
}
void client::start_thread3()
{
std::thread t(&client::thread3,this);
t.detach();
}
void* client::thread3(void* _this)
{
client*p = (client*) _this;
p->send_news();
return p;
}
client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QObject>
#include<QString>
#include<Qtimer.h>
#include<thread>
#include<Windows.h>
#include<qdebug.h>
#pragma comment(lib,"ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
using namespace std;
class client : public QObject
{
Q_OBJECT
//Exposed to QML attributes
Q_PROPERTY(QString mystring READ getString WRITE setString NOTIFY mystringChanged)
Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged)
public:
explicit client(QObject *parent = 0);
~client();
Q_INVOKABLE QString getString(); //Q_INVOCABLE is exposed to QML
Q_INVOKABLE void setString(QString string);
Q_INVOKABLE QString message();
Q_INVOKABLE void setMessage(QString string);
Q_INVOKABLE void sendMessage(QString string);
Q_INVOKABLE void obtain_message(QString str);
Q_INVOKABLE QString get_send_data();
void communication();
void recv_news();
void send_news();
signals:
void mystringChanged(QString value); //signal
void messageChanged(QString str);
public slots:
Q_INVOKABLE void connect_server();
static void*thread1(void*);
static void*thread2(void*);
static void*thread3(void*);
void start_thread1();
void start_thread2();
void start_thread3();
public:
QString * m_pstring;
QString *send_data;
QString *recv_data;
};
#endif // MYCLASS_H
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include"client.h"
#include<QtQml>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<client>("RegisterClient",1,0,"Client");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
How to use the chat software:
1. After running Server and Client, first start the server and click Connect, then click the client Connect.
2. When the prompt on the upper right becomes waiting connect... and connect succeed, you can achieve duplex sending and receiving of messages.
ps: The upper left corner shows the real-time message. Click the recvmsg button to record the current message and display the message in the box.
Effect picture
Note: The chat box and the icon material can be selected arbitrarily
这篇关于Small chat software based on C++/qml (including source code)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享