QListWidget类提供了一个基于item的列表小部件。QListWidget是一个方便的类,它提供了类似于QlistView所具有的列表视图,但是具有增加和删除的功能。QListWidget使用内部模型来管理列表中的每个QListWidgetItem。想要有更灵活的列表视图,请使用具有标准模型的QListView类。
服务器端代码
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include<QPushButton>
#include<QLabel>
#include<QTextEdit>
#include<QLineEdit>
#include<QGridLayout>
#include<QListWidget>
#include"serverh.h"
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QPushButton *CreatButton;
QGridLayout *mainLayout;
QLineEdit *PortLineEdit;
QListWidget *listwidget;
QLabel *PortLabel;
private:
int port;
serverh *server;
public slots:
void slotCreatServer();
void slotupdateServer(QString,int);
};
#endif // DIALOG_H
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
listwidget=new QListWidget;
setWindowTitle(tr("tcp Server"));
PortLabel =new QLabel(QStringLiteral("端口:"),this);
PortLineEdit=new QLineEdit(this);
CreatButton=new QPushButton(this);
CreatButton->setText(QStringLiteral("创建聊天室"));
mainLayout=new QGridLayout(this);
mainLayout->addWidget(listwidget,0,0,1,2);
mainLayout->addWidget(PortLabel,1,0);
mainLayout->addWidget(PortLineEdit,1,1);
mainLayout->addWidget(CreatButton,2,0,1,2);
port=8010;
PortLineEdit->setText(QString::number(port));
connect(CreatButton,&QPushButton::clicked,this,&Dialog::slotCreatServer);
}
Dialog::~Dialog()
{
}
void Dialog::slotCreatServer()
{
server=new serverh(this,port);
connect(server,&serverh::updateServer,this,&Dialog::slotupdateServer);
CreatButton->setEnabled(false);
}
void Dialog::slotupdateServer(QString msg, int length)//用于更新服务器上的信息显示
{
listwidget->addItem(msg.left(length));//从左开始数length长度
}
#ifndef SERVERH_H
#define SERVERH_H
#include<QtNetwork/QTcpServer>
#include<QObject>
#include"tcpclicentsocket.h"
class serverh:public QTcpServer
{
Q_OBJECT
public:
serverh(QObject *parent=0,int port=0);
QList<tcpclicentsocket*> tcpClicentSocketList;
signals:
void updateServer(QString,int);
public slots:
void updateClicents(QString,int);
void slotDisconnected(int);
protected:
void incomingConnection(int socketDescriptor);
};
#endif // SERVERH_H
#include "serverh.h"
serverh::serverh(QObject *parent,int port)
{
listen(QHostAddress::Any,port);//在指定的端口对任意地址监听,Any表示ipv4的任意地址
}
void serverh::updateClicents(QString msg, int length)//将任意客户端发来的信息进行广播
{
emit updateServer(msg,length);
for(int i=0;i<tcpClicentSocketList.count();i++)
{
QTcpSocket *item=tcpClicentSocketList.at(i);
if(item->write(msg.toLatin1(),length)!=length)
{
continue;
}
}
}
void serverh::slotDisconnected(int descriptor)
{
for(int i=0;i<tcpClicentSocketList.count();i++)
{
QTcpSocket *item=tcpClicentSocketList.at(i);
if(item->socketDescriptor()==descriptor)
{
tcpClicentSocketList.removeAt(i);//断开这个客户端
return;
}
}
}
void serverh::incomingConnection(int socketDescriptor)
{
tcpclicentsocket *tcpClicentSocket=new tcpclicentsocket(this);
//创建一个新的tcpclientsocket来与客户端通信
connect(tcpClicentSocket,&tcpclicentsocket::updateClicent,this,&serverh::updateClicents);
connect(tcpClicentSocket,&tcpclicentsocket::disconnected,this,&serverh::slotDisconnected);
tcpClicentSocket->setSocketDescriptor(socketDescriptor);//指定了连接的socket描述符
tcpClicentSocketList.append(tcpClicentSocket);//加入链表中方便管理
}
#ifndef TCPCLICENTSOCKET_H
#define TCPCLICENTSOCKET_H
#include<QtNetwork/QTcpSocket>
#include<QObject>
class tcpclicentsocket:public QTcpSocket
{
Q_OBJECT
public:
tcpclicentsocket(QObject *parent);
signals:
void updateClicent(QString,int);//通知服务器想聊天室内的所有的成员广播信息
void disconnected(int);
protected slots:
void dataReceived();
void slotDisconnected();
};
#endif // TCPCLICENTSOCKET_H
#include "tcpclicentsocket.h"
tcpclicentsocket::tcpclicentsocket(QObject *parent)
{
connect(this,&tcpclicentsocket::readyRead,this,&tcpclicentsocket::dataReceived);
connect(this,&tcpclicentsocket::disconnected,this,&tcpclicentsocket::slotDisconnected);
}
void tcpclicentsocket::dataReceived()//将套接字中的有效数据读出
{
while(bytesAvailable()>0)
{
int length=bytesAvailable();//获得数据的大小
char buf[1024];
read(buf,length);
QString msg=buf;
emit updateClicent(msg,length);
}
}
void tcpclicentsocket::slotDisconnected()
{
emit disconnected(this->socketDescriptor());
}
客户端代码
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include<QListWidget>
#include<QLineEdit>
#include<QPushButton>
#include<QLabel>
#include<QGridLayout>
#include<QHostAddress>
#include<QTcpSocket>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
~Dialog();
private:
QListWidget *listwidget;
QPushButton *sendButton;
QPushButton *enterButton;
QLineEdit *sendLineEdit;
QLabel *UsernameLabel;
QLineEdit* UserLineEdit;
QLabel *ServerLabel;
QLineEdit *ServerLineEdit;
QLabel *portLabel;
QLineEdit *portLineEdit;
QGridLayout *mainLayout;
private:
int port;
bool status;
QHostAddress *serverIp;
QString username;
QTcpSocket *tcpsocket;
public slots:
void slotEnter();
void slotConnected();
void slotDisconnected();
void dataReceived();
void slotSend();
};
#endif // DIALOG_H
#include "dialog.h"
#include<QMessageBox>
#include<QHostInfo>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(tr("Tcp slicent"));
listwidget=new QListWidget;
sendLineEdit=new QLineEdit(this);
sendButton=new QPushButton(this);
sendButton->setText(QStringLiteral("发送"));
UsernameLabel=new QLabel(this);
UsernameLabel->setText(QStringLiteral("用户名"));
UserLineEdit=new QLineEdit(this);
ServerLabel=new QLabel(this);
ServerLabel->setText(QStringLiteral("服务器地址"));
ServerLineEdit=new QLineEdit(this);
portLabel=new QLabel(tr("端口"),this);
portLineEdit=new QLineEdit(this);
enterButton=new QPushButton(this);
enterButton->setText(QStringLiteral("进入聊天室"));
mainLayout=new QGridLayout(this);
mainLayout->addWidget(listwidget,0,0,1,2);
mainLayout->addWidget(sendLineEdit,1,0);
mainLayout->addWidget(sendButton,1,1);
mainLayout->addWidget(UsernameLabel,2,0);
mainLayout->addWidget(UserLineEdit,2,1);
mainLayout->addWidget(ServerLabel,3,0);
mainLayout->addWidget(ServerLineEdit,3,1);
mainLayout->addWidget(portLabel,4,0);
mainLayout->addWidget(portLineEdit,4,1);
mainLayout->addWidget(enterButton,5,0,2,1);
status=false;
port=8010;
portLineEdit->setText(QString::number(port));
serverIp=new QHostAddress();
connect(enterButton,&QPushButton::clicked,this,&Dialog::slotEnter);
connect(sendButton,&QPushButton::clicked,this,&Dialog::slotSend);
sendButton->setEnabled(false);
}
Dialog::~Dialog()
{
}
void Dialog::slotEnter()
{
if(!status)
{
QString ip=ServerLineEdit->text();
if(!serverIp->setAddress(ip))
{
QMessageBox::information(this,tr("error"),tr("server ip is error"));
return;
}
if(UserLineEdit->text()=="")
{
QMessageBox::information(this,tr("error"),tr("user name error"));
return;
}
username=UserLineEdit->text();
tcpsocket=new QTcpSocket(this);
connect(tcpsocket,&QTcpSocket::connected,this,&Dialog::slotConnected);
connect(tcpsocket,&QTcpSocket::disconnected,this,&Dialog::slotDisconnected);
connect(tcpsocket,&QTcpSocket::readyRead,this,&Dialog::dataReceived);
tcpsocket->connectToHost(*serverIp,port);
status=true;
}
else {
int length=0;
QString msg=username+tr("leave chat room");//构造一条离开聊天室的信息
if((length=tcpsocket->write(msg.toLatin1(),msg.length()))!=msg.length())
{
return;
}
tcpsocket->disconnectFromHost();//与服务器断开连接
status=false;
}
}
void Dialog::slotConnected()
{
sendButton->setEnabled(true);
enterButton->setText(tr("离开"));
int length=0;
QString msg=username+tr("enter chat room");
if((length=tcpsocket->write(msg.toLatin1(),msg.length()))!=msg.length())
{
return;
}
}
void Dialog::slotDisconnected()
{
sendButton->setEnabled(false);
enterButton->setText(tr("进入聊天室"));
}
void Dialog::dataReceived()
{
while(tcpsocket->bytesAvailable()>0)
{
QByteArray datagram;
datagram.resize(tcpsocket->bytesAvailable());
tcpsocket->read(datagram.data(),datagram.size());
QString msg=datagram.data();
listwidget->addItem(msg.left(datagram.size()));
}
}
void Dialog::slotSend()
{
if(sendLineEdit->text()=="")
{
return;
}
QString msg=sendLineEdit->text();
tcpsocket->write(msg.toLatin1(),msg.length());
sendLineEdit->clear();//删除已经输入的内容
}