QT 聊天程序

一.聊天程序
QT实现的界面
网络的数据通信
服务器端
建立用户UI
建立服务器socket
接受客户连接
为每个各户建立线程处理客户数据

分析设计的一般规律:
1.用例
2.事件流
3.找对象,并且抽象类
4.设计类本身
5.设计类关系(泛化关系,关联关系)
6.设计模式优化设计


设计界面
QMainWindow增加:菜单,工具条,状态条。
菜单:
QMenuBar
addMenu
QMenu
addAction
QMenuItem/QAction
构造器

菜单的响应
状态条

QStatusBar

服务器设计图



ServerSocket.h

<span style="font-size:18px;">#ifndef SERVER_SOCKET_H
#define SERVER_SOCKET_H
#include <QObject>
#include "ChatException.h"
class ServerSocket : public QObject
{
Q_OBJECT
public:
	char ip[30];
	short port;
	int fd;
public:
	void initSocket() throw (ChatException);  // 初始化Socket
	int accept() throw (ChatException); // 返回客户的文件描述符
};
#endif
</span>

ServerSocket.cpp

<span style="font-size:18px;">#include "ServerSocket.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
void ServerSocket::initSocket()throw(ChatException)
{
	struct sockaddr_in addr;
	int r;
	fd=socket(AF_INET,SOCK_STREAM,0);
	if(fd==-1) throw ChatException("socket错误");
	
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=inet_addr(ip);
	addr.sin_port=htons(port);
	r=bind(fd,(struct sockaddr*)&addr,sizeof(addr));
	if(r==-1) {
		close(fd);
		throw ChatException("bind错误");
	}
	
	r=listen(fd,10);
	if(r==-1){
		close(fd);
		throw ChatException("listen错误");
	}
}
int ServerSocket::accept()throw(ChatException)
{
	int cfd;
	cfd=::accept(fd,NULL,0);  // 表明是全局函数
	if(cfd==-1) throw ChatException("accept错误");
	return cfd;
}
</span>

ThAccept.h

<span style="font-size:18px;">#ifndef TH_ACCEPT_H
#define TH_ACCEPT_H
#include <QThread>
#include "ChatException.h"
#include "ServerSocket.h"
#include <QTextEdit>
class ThAccept : public QThread
{
Q_OBJECT
public:
	QTextEdit *info;
private:
	ServerSocket server;
public:
	void init()throw(ChatException);
	void run();//在线程中接收客户连接
public: signals:
	void sigInfo(const QString &);	 // 和append函数保持一致
};
#endif</span>

ThAccept.cpp

<span style="font-size:18px;">#include "ThAccept.h"
#include <cstdio>
#include "ThClient.h"
#include "ServerWindow.h"
using namespace std;
void ThAccept::init()throw(ChatException)
{
	sprintf(server.ip,"%s","192.168.180.92");
	server.port=8888;
	try{
		server.initSocket();
	}
	catch(ChatException e)
	{
		throw e;
	}
}
void ThAccept::run()//在线程中接收客户连接
{
	while(true)
	{
		try	{
			int fd=server.accept();
			//发出信号			
			emit sigInfo(tr("有人连接!"));
			//??建立子线程监听对应的客户
			ThClient *th=new ThClient;
			th->fd=fd;
			ServerWindow::allusers.push_back(th);
			connect(th,SIGNAL(sigInfo(const QString&)),
			info,SLOT(append(const QString&)));	
			th->start();
		}
		catch(ChatException e)
		{
			//发出信号
			emit sigInfo("服务器崩溃!");
			break;
		}
	}
	
}
</span>

ThClient.h

<span style="font-size:18px;">#ifndef TH_CLIENT_H
#define TH_CLIENT_H
#include <QThread>
class ThClient : public QThread
{
Q_OBJECT
public:
	int fd;
public:	
	void run(); //接收客户数据,广播
public: signals:
	void sigInfo(const QString&);
};
#endif
</span>

ThClient.cpp

<span style="font-size:18px;">#include "ThClient.h"
#include <sys/socket.h>
#include <list>
#include "ServerWindow.h"
#include <unistd.h>
using namespace std;
void ThClient::run()
{
	int r;
	char buf[1024];
	while(true)
	{
		r=recv(fd,buf,sizeof(buf)-1,0);
		if(r<=0) 
		{			
			emit sigInfo(tr("有客户退出"));
			ServerWindow::allusers.remove(this);
			close(fd);
			//delete this;
			break;
		}
		buf[r]=0;
		//发送消息,把接收数据显示到服务器主窗体
		emit sigInfo(tr(buf));
		//广播
		list<ThClient*>::iterator it=
			ServerWindow::allusers.begin();
		while(it!=ServerWindow::allusers.end())
		{
			send((*it)->fd,buf,strlen(buf),0);
			it++;
		}
	}
}
</span>

ServerWindow.h

<span style="font-size:18px;">#ifndef SERVER_WINDOW_H
#define SERVER_WINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QTextEdit>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QStatusBar>
#include <QLabel>
#include "ThAccept.h"
#include <list>
#include "ThClient.h"
using namespace std;
class ServerWindow : public QMainWindow
{
Q_OBJECT
public:
	static list<ThClient*>  allusers;
private:
	QTextEdit *info;//显示聊天信息
	//菜单
	QMenuBar  *bar;
	QMenu	  *mnuserver;
	QAction	  *actstart;  // 创建服务器
	QAction	  *actexit;   // 退出服务器
	//状态条
	QStatusBar *status;   // 
	QLabel 	   *lbltip;   // 操作提示
	QLabel	   *lblresult;// 操作结果
	QLabel	   *lbltime;	// 显示时间
	//接收线程		
	ThAccept  thaccept;
public:
	ServerWindow(QWidget*p=NULL);
public slots:
	void onStart();
};
#endif
</span>

ServerWindow.cpp

<span style="font-size:18px;">#ifndef SERVER_WINDOW_H
#define SERVER_WINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QTextEdit>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QStatusBar>
#include <QLabel>
#include "ThAccept.h"
#include <list>
#include "ThClient.h"
using namespace std;
class ServerWindow : public QMainWindow
{
Q_OBJECT
public:
	static list<ThClient*>  allusers;
private:
	QTextEdit *info;//显示聊天信息
	//菜单
	QMenuBar  *bar;
	QMenu	  *mnuserver;
	QAction	  *actstart;  // 创建服务器
	QAction	  *actexit;   // 退出服务器
	//状态条
	QStatusBar *status;   // 
	QLabel 	   *lbltip;   // 操作提示
	QLabel	   *lblresult;// 操作结果
	QLabel	   *lbltime;	// 显示时间
	//接收线程		
	ThAccept  thaccept;
public:
	ServerWindow(QWidget*p=NULL);
public slots:
	void onStart();
};
#endif
</span>
ChatServer.h

<span style="font-size:18px;">#ifndef CHAT_EXCEPTION_H
#define CHAT_EXCEPTION_H
#include <exception>
using namespace std;
class ChatException : public exception
{
private:
	char msg[50];
public:
	ChatException();
	ChatException(const char*);
	const char* what() const throw();
};
#endif
</span>

ChatServer.cpp

<span style="font-size:18px;">#include "ChatException.h"
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
ChatException::ChatException(){
	memset(msg,0,sizeof(msg));
	sprintf(msg,"聊天异常!");
}
ChatException::ChatException(const char*m){
	memset(msg,0,sizeof(msg));
	sprintf(msg,"聊天异常:%s!",m);
}

const char* ChatException::what() const throw(){
	return msg;
}
</span>


chatServer.cpp 主程序

<span style="font-size:18px;">#include <QApplication>
#include <QTextCodec>
#include "ServerWindow.h"
int main(int args,char**argv)
{
	QApplication app(args,argv);
	QTextCodec *codec=
		QTextCodec::codecForName("gb2312");
	QTextCodec::setCodecForTr(codec);
	ServerWindow sw;	
	return app.exec();
}<span style="color:#ff0000;">
</span></span>

chatServer.pro

<span style="font-size:18px;">TEMPLATE=app
SOURCES=chatServer.cpp		\
		ServerWindow.cpp	\
		ChatException.cpp	\
		ServerSocket.cpp	\
		ThAccept.cpp		\
		ThClient.cpp
HEADERS=ServerWindow.h		\
		ChatException.h		\
		ServerSocket.h		\
		ThAccept.h			\
		ThClient.h
			
CONFIG=release qt
QT=core gui
TARGET=server
</span>



Qt聊天程序的UI设计原理主要是基于Qt框架提供的UI组件和布局管理器进行设计。在Qt中,可以使用QWidget、QMainWindow或QDialog等窗口类作为聊天程序的主窗口,然后通过添加各种UI组件(如QLabel、QLineEdit、QPushButton等)来构建聊天界面。 首先,要确定聊天界面的整体布局。可以使用QHBoxLayout、QVBoxLayout或QGridLayout等布局管理器来安排UI组件的位置和大小,以达到预期的界面效果。 接下来,可以使用QLabel或QTextEdit等组件来显示聊天记录,可以使用QLineEdit或QPlainTextEdit等组件作为输入框接收用户输入。还可以使用QPushButton或QToolButton等按钮组件添加发送消息的按钮,以及其他功能按钮。 对于聊天记录的显示,可以使用QListView或QTextEdit等组件,通过设置相应的模型(如QStringListModel或QStandardItemModel)来实现数据的展示和更新。 对于聊天窗口的样式设计,可以使用Qt提供的样式表功能进行自定义。通过设置组件的样式属性(如背景色、字体、边框等)来实现个性化的界面效果。 除了基本的UI组件外,还可以考虑添加一些额外的功能,比如头像显示、表情符号选择、文件传输等,可以根据求选择合适的UI组件进行扩展。 总之,Qt聊天程序的UI设计原理是通过利用Qt提供的UI组件和布局管理器来构建界面,同时可以借助Qt的样式表功能实现个性化的界面效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值