QT网络聊天室

QT基于TCP网络聊天室

1.客户端

1.1UI设计

​ 分两个部分,第一部分是消息区里面包含QPlainTextEditQListWidget,要显示接收的消息和在线的成员。第二部分QLineEdit发生字符。

1.2 子模块

1.2.1 登录界面

​ 登录界面主要就是要有验证码,防止恶意程序的攻击。通过paintEvent画出一个白色矩形,在白色矩形里面显示四个不同颜色的字母以及随机出现的噪点。

代码:

QLoginDialog.h

#ifndef _QLOGINDIALOG_H_
#define _QLOGINDIALOG_H_

#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QTimer>

//继承自Dialog
class QLoginDialog : public QDialog
{
    Q_OBJECT
public:
    typedef bool (*ValFunc)(QString);
private:
    QLabel UserLabel;
    QLabel PwdLabel;
    QLabel CaptLabel;
    QLineEdit UserEdit;
    QLineEdit PwdEdit;
    QLineEdit CaptEdit;
    QPushButton LoginBtn;
    QPushButton CancelBtn;
    QString m_user;
    QString m_pwd;
    QString m_captcha;
    Qt::GlobalColor* m_colors;
    QTimer m_timer;
    ValFunc m_vf;
private slots:
    void LoginBtn_Clicked();
    void CancelBtn_Clicked();
    void Timer_Timeout();
protected:
    void paintEvent(QPaintEvent *);
    QString getCaptcha();
    Qt::GlobalColor* getColors();
    void showEvent(QShowEvent *);
public:
    QLoginDialog(QWidget *parent = 0);
    QString getUser();
    QString getPwd();
    void setValFunc(ValFunc);
    ~QLoginDialog();
};


#endif

QLoginDialog.cpp

#include "QLoginDialog.h"
#include <QPainter>
#include <QTime>
#include <QMessageBox>



QLoginDialog::QLoginDialog(QWidget* parent) : QDialog(parent, Qt::WindowCloseButtonHint),
    UserLabel(this), PwdLabel(this), CaptLabel(this),
    UserEdit(this), PwdEdit(this), CaptEdit(this),
    LoginBtn(this), CancelBtn(this),
    m_vf(NULL)
{
    UserLabel.setText("用户名:");
    UserLabel.move(20, 30);
    UserLabel.resize(60, 25);

    UserEdit.move(85, 30);
    UserEdit.resize(180, 25);

    PwdLabel.setText("密  码:");
    PwdLabel.move(20, 65);
    PwdLabel.resize(60,25);

    PwdEdit.move(85, 65);
    PwdEdit.resize(180, 25);
    PwdEdit.setEchoMode(QLineEdit::Password);

    CaptLabel.setText("验证码:");
    CaptLabel.move(20, 100);
    CaptLabel.resize(60, 25);

    CaptEdit.move(85, 100);
    CaptEdit.resize(85, 25);

    CancelBtn.setText("取消");
    CancelBtn.move(85, 145);
    CancelBtn.resize(85, 30);

    LoginBtn.setText("登录");
    LoginBtn.move(180, 145);
    LoginBtn.resize(85, 30);

    m_timer.setParent(this);

    setWindowTitle("登录...");
    setFixedSize(285, 205);

    connect(&m_timer, SIGNAL(timeout()), this, SLOT(Timer_Timeout()));
    connect(&LoginBtn, SIGNAL(clicked()), this, SLOT(LoginBtn_Clicked()));
    connect(&CancelBtn, SIGNAL(clicked()), this, SLOT(CancelBtn_Clicked()));

    //以时间作为种子,获取随机数
    qsrand(QTime::currentTime().second() * 1000 + QTime::currentTime().msec());

    m_timer.start(100);
}

void QLoginDialog::LoginBtn_Clicked()
{
    //去除空格
    QString captcha = CaptEdit.text().replace(" ", "");
	
    //校验验证码
    if( m_captcha.toLower() == captcha.toLower() )
    {
        m_user = UserEdit.text().trimmed();
        m_pwd = PwdEdit.text();

        if( m_user == "" )
        {
            QMessageBox::information(this, "消息", "用户名不能为空!");
        }
        else if( m_pwd == "" )
        {
            QMessageBox::information(this, "消息", "密码不能为空!");
        }
        else if( (m_vf != NULL) && !(m_vf(m_user)))  //一些非法字符不可输入
        {
            QMessageBox::information(this, "消息", "用户名非法,请重新输入!");
        }
        else
        {
            done(Accepted);
        }
    }
    else
    {
        QMessageBox::critical(this, "错误", "验证码输入错误!");

        m_captcha = getCaptcha();

        CaptEdit.selectAll();
    }
}

void QLoginDialog::setValFunc(ValFunc vf)
{
    m_vf = vf;
}

void QLoginDialog::CancelBtn_Clicked()
{
    done(Rejected);
}

QString QLoginDialog::getUser()
{
    return m_user;
}

QString QLoginDialog::getPwd()
{
    return m_pwd;
}

//获取四个随机的颜色
Qt::GlobalColor* QLoginDialog::getColors()
{
    static Qt::GlobalColor colors[4];

    for(int i=0; i<4; i++)
    {
        colors[i] = static_cast<Qt::GlobalColor>(2 + qrand() % 16);
    }

    return colors;
}


void QLoginDialog::Timer_Timeout()
{
    //每100毫秒获取四种颜色
    m_colors = getColors();

    //更新画板
    update();
}

void QLoginDialog::showEvent(QShowEvent* event)
{
    //每次显示之前,获取验证码和颜色
    m_captcha = getCaptcha();
    m_colors = getColors();

    QDialog::showEvent(event);
}

void QLoginDialog::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
	
    //获取一个矩形
    painter.fillRect(180, 100, 84, 24, Qt::white);

    painter.setFont(QFont("Comic Sans MS", 12));

    //填充噪点,150个点随机显示
    for(int i=0; i<150; i++)
    {
        painter.setPen(m_colors[i%4]);
        painter.drawPoint(180 + qrand() % 84, 100 + qrand() % 24);
    }
	
    //验证码四个颜色
    for(int i=0; i<4; i++)
    {
        painter.setPen(m_colors[i]);
        painter.drawText(180 + 20 * i, 100, 20, 24, Qt::AlignCenter, QString(m_captcha[i]));
    }

    QDialog::paintEvent(event);
}

QString QLoginDialog::getCaptcha()
{
    QString ret = "";

    for(int i=0; i<4; i++)
    {
        int c = (qrand() % 2) ? 'a' : 'A';

        ret += static_cast<QChar>(c + qrand() % 26);
    }

    return ret;
}

QLoginDialog::~QLoginDialog()
{

}
1.2.2 协议
1.2.2.1 协议的制订

客户端与服务端之间的操作需要用到协议,能够方便解析客户端需要的操作。

操作类型+数据长度+数据

TextMessage.h

#ifndef TEXTMESSAGE_H
#define TEXTMESSAGE_H

#include <QObject>
#include <QByteArray>

class TextMessage : public QObject
{
    Q_OBJECT
    QString m_type;
    QString m_data;

public:
    TextMessage(QObject *parent = 0);
    TextMessage(QString type,QString data,QObject* parent = NULL);

    QString type();
    int length();
    QString data();

    QByteArray serizlize();
    bool unserialize(QByteArray ba);

};

#endif // TEXTMESSAGE_H

TextMessage.cpp

#include "TextMessage.h"
#include <QString>
#include <QDebug>
TextMessage::TextMessage(QObject *parent) : QObject(parent)
{
    m_type = "";
    m_data = "";
}


TextMessage::TextMessage(QString type,QString data,QObject* parent)
{

    m_type = type.trimmed();

    if(m_type.length() < 4)
    {
        m_type += QString(4-m_type.length(),' ');
    }


    m_data = data.mid(0, 15000);


}

QString TextMessage::type()
{
    return m_type.trimmed();
}


int TextMessage::length()
{
    return m_data.length();
}

QString TextMessage::data()
{
    return m_data;
}

//把需要发送的数据转换成协议
QByteArray TextMessage::serizlize()
{
    QByteArray ret;
    QByteArray dba = m_data.toUtf8();

    QString len = QString::asprintf("%X",dba.length());

    if(len.length() < 4)
    {
        len += QString(4-len.length(),' ');
    }
    ret.append(m_type.toStdString().c_str(),4);
    ret.append(len.toStdString().c_str(),4);
    ret.append(dba);

    return ret;
}

//把接收的协议转换为具体的数据
bool TextMessage::unserialize(QByteArray ba)
{
    bool ret = (ba.length() >= 8);

    if(ret)
    {
        QString type = QString(ba.mid(0,4));
        QString len = QString(ba.mid(4,4)).trimmed();
        int l = len.toInt(&r
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值