qt官网示例小软件----局域网聊天软件

这篇博客介绍了使用QT框架进行网络编程实验,创建一个局域网聊天软件的过程。作者分享了从QT官网获取的易于上手的示例代码,并逐步解析了工程配置、界面设计和网络库的使用,帮助读者加深对QT应用的理解。

最近在做网络编程实验,要求用到图形界面,于是又重拾了QT这个非常喜欢的C++框架。在QT官网上找到了一个特别容易上手的小软件,在此和大家一起分享,并加强一下对QT的应用。


点击打开链接

这是代码的网址




最后软件的样子,接下来就一段代码一段代码的分析。


首先是工程


</pre>HEADERS       = chatdialog.h \                client.h \                connection.h \                peermanager.h \                server.hSOURCES       = chatdialog.cpp \                client.cpp \                connection.cpp \                main.cpp \                peermanager.cpp \                server.cppFORMS         = chatdialog.uiQT           += network widgets# installtarget.path = $$[QT_INSTALL_EXAMPLES]/network/network-chatINSTALLS += target 和普通的qmake文件没什么太大区别,注意要加上 QT += network widgets ,只有加上这个QT 才能有网络库。接下来是整个界面的定义,Chatdialog.h#ifndef CHATDIALOG_H#define CHATDIALOG_H#include "ui_chatdialog.h"#include "client.h"class ChatDialog : public QDialog, private Ui::ChatDialog{    Q_OBJECTpublic:    ChatDialog(QWidget *parent = 0);public slots:    void appendMessage(const QString &from, const QString &message);private slots:    void returnPressed();    void newParticipant(const QString &nick);    void participantLeft(const QString &nick);    void showInformation();private:    Client client;    QString myNickName;    QTextTableFormat tableFormat;};#endif然后是界面的实现Chatdialog.cpp#include <QtWidgets>#include "chatdialog.h"ChatDialog::ChatDialog(QWidget *parent)    : QDialog(parent){    setupUi(this);    lineEdit->setFocusPolicy(Qt::StrongFocus); 	//将光标锁定在lineEdit      textEdit->setFocusPolicy(Qt::NoFocus);		//光标不会出现在textedit,listwidget      textEdit->setReadOnly(true);    listWidget->setFocusPolicy(Qt::NoFocus);    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));    connect(&client, SIGNAL(newMessage(QString,QString)),            this, SLOT(appendMessage(QString,QString)));    connect(&client, SIGNAL(newParticipant(QString)),            this, SLOT(newParticipant(QString)));    connect(&client, SIGNAL(participantLeft(QString)),            this, SLOT(participantLeft(QString)));    myNickName = client.nickName();	//返回用户名,nickName()是自己定义的一个函数      newParticipant(myNickName);    tableFormat.setBorder(0);		//设置界面边沿宽度为0      QTimer::singleShot(10 * 1000, this, SLOT(showInformation()));//程序在10秒后会调用一个槽showInformation()  }void ChatDialog::appendMessage(const QString &from, const QString &message){    if (from.isEmpty() || message.isEmpty())        return;    QTextCursor cursor(textEdit->textCursor());    cursor.movePosition(QTextCursor::End);	//将textEdit里的光标设置在文字的最后,以免输出混乱      QTextTable *table = cursor.insertTable(1, 2, tableFormat);    table->cellAt(0, 0).firstCursorPosition().insertText('<' + from + "> ");table->cellAt(0, 1).firstCursorPosition().insertText(message); //设置textEdit的输出格式    QScrollBar *bar = textEdit->verticalScrollBar();//设置textEdit支持垂直滚动      bar->setValue(bar->maximum());}void ChatDialog::returnPressed(){    QString text = lineEdit->text();    if (text.isEmpty())        return;    if (text.startsWith(QChar('/'))) {			//输入以"/"打头的字符会报错          QColor color = textEdit->textColor();        textEdit->setTextColor(Qt::red);	//报错内容为红色          textEdit->append(tr("! Unknown command: %1")                         .arg(text.left(text.indexOf(' '))));        textEdit->setTextColor(color);		//将输出内容重新设为黑色      } else {        client.sendMessage(text);	//发送给客户机文本信息          appendMessage(myNickName, text); //在本机上显示文本信息      }    lineEdit->clear();}void ChatDialog::newParticipant(const QString &nick){    if (nick.isEmpty())        return;    QColor color = textEdit->textColor();    textEdit->setTextColor(Qt::gray); //将加入者信息输出设为灰色      textEdit->append(tr("* %1 has joined").arg(nick));    textEdit->setTextColor(color); /重设为黑色     listWidget->addItem(nick); 	//在listWidget栏内添加新的成员  }void ChatDialog::participantLeft(const QString &nick){    if (nick.isEmpty())        return;    QList<QListWidgetItem *> items = listWidget->findItems(nick,                                                           Qt::MatchExactly);	//在listWidget栏中找到离开者的项      if (items.isEmpty())        return;    delete items.at(0);	//删除项      QColor color = textEdit->textColor();    textEdit->setTextColor(Qt::gray);    textEdit->append(tr("* %1 has left").arg(nick)); //输出相应信息      textEdit->setTextColor(color);}void ChatDialog::showInformation()		//十秒后输出的信息  {    if (listWidget->count() == 1) {        QMessageBox::information(this, tr("Chat"),                                 tr("Launch several instances of this "                                    "program on your local network and "                                    "start chatting!"));    }}接下来是客户机的定义:Client.h#ifndef CLIENT_H#define CLIENT_H#include <QAbstractSocket>#include <QHash>#include <QHostAddress>#include "server.h"class PeerManager;class Client : public QObject{    Q_OBJECTpublic:    Client();    void sendMessage(const QString &message);    QString nickName() const;    bool hasConnection(const QHostAddress &senderIp, int senderPort = -1) const;signals:    void newMessage(const QString &from, const QString &message);    void newParticipant(const QString &nick);    void participantLeft(const QString &nick);private slots:    void newConnection(Connection *connection);    void connectionError(QAbstractSocket::SocketError socketError);    void disconnected();    void readyForUse();private:    void removeConnection(Connection *connection);    PeerManager *peerManager;    Server server;    QMultiHash<QHostAddress, Connection *> peers;};#endif客户机的实现Client.cpp#include <QtNetwork>#include "client.h"#include "connection.h"#include "peermanager.h"Client::Client(){    peerManager = new PeerManager(this);    peerManager->setServerPort(server.serverPort());       //将peerManager的端口设置为服务器的端口    peerManager->startBroadcasting();    QObject::connect(peerManager, SIGNAL(newConnection(Connection*)),                     this, SLOT(newConnection(Connection*)));    QObject::connect(&server, SIGNAL(newConnection(Connection*)),                     this, SLOT(newConnection(Connection*)));}void Client::sendMessage(const QString &message){    if (message.isEmpty())        return;    QList<Connection *> connections = peers.values();    foreach (Connection *connection, connections)   //一个宏,对于每个连接都执行sendMessage()      connection->sendMessage(message);}QString Client::nickName() const{    return QString(peerManager->userName()) + '@' + QHostInfo::localHostName()           + ':' + QString::number(server.serverPort());}bool Client::hasConnection(const QHostAddress &senderIp, int senderPort) const{    if (senderPort == -1)        return peers.contains(senderIp);    if (!peers.contains(senderIp))        return false;    QList<Connection *> connections = peers.values(senderIp);    foreach (Connection *connection, connections) {        if (connection->peerPort() == senderPort)            return true;    }    return false;}void Client::newConnection(Connection *connection){    connection->setGreetingMessage(peerManager->userName());    connect(connection, SIGNAL(error(QAbstractSocket::SocketError)),            this, SLOT(connectionError(QAbstractSocket::SocketError)));    connect(connection, SIGNAL(disconnected()), this, SLOT(disconnected()));    connect(connection, SIGNAL(readyForUse()), this, SLOT(readyForUse()));}void Client::readyForUse(){    Connection *connection = qobject_cast<Connection *>(sender());    if (!connection || hasConnection(connection->peerAddress(),                                     connection->peerPort()))        return;    connect(connection, SIGNAL(newMessage(QString,QString)),            this, SIGNAL(newMessage(QString,QString)));    peers.insert(connection->peerAddress(), connection);    QString nick = connection->name();    if (!nick.isEmpty())        emit newParticipant(nick);}void Client::disconnected(){    if (Connection *connection = qobject_cast<Connection *>(sender()))        removeConnection(connection);}void Client::connectionError(QAbstractSocket::SocketError /* socketError */){    if (Connection *connection = qobject_cast<Connection *>(sender()))        removeConnection(connection);}void Client::removeConnection(Connection *connection){    if (peers.contains(connection->peerAddress())) {        peers.remove(connection->peerAddress());        QString nick = connection->name();        if (!nick.isEmpty())            emit participantLeft(nick);    }    connection->deleteLater();}连接的定义Connect.h#ifndef CONNECTION_H#define CONNECTION_H#include <QHostAddress>#include <QString>#include <QTcpSocket>#include <QTime>#include <QTimer>static const int MaxBufferSize = 1024000;class Connection : public QTcpSocket{    Q_OBJECTpublic:    enum ConnectionState {        WaitingForGreeting,        ReadingGreeting,        ReadyForUse    };    enum DataType {        PlainText,        Ping,        Pong,        Greeting,        Undefined    };    Connection(QObject *parent = 0);    QString name() const;    void setGreetingMessage(const QString &message);    bool sendMessage(const QString &message);signals:    void readyForUse();    void newMessage(const QString &from, const QString &message);protected:    void timerEvent(QTimerEvent *timerEvent) Q_DECL_OVERRIDE;private slots:    void processReadyRead();    void sendPing();    void sendGreetingMessage();private:    int readDataIntoBuffer(int maxSize = MaxBufferSize);    int dataLengthForCurrentDataType();    bool readProtocolHeader();    bool hasEnoughData();    void processData();    QString greetingMessage;    QString username;    QTimer pingTimer;    QTime pongTime;    QByteArray buffer;    ConnectionState state;    DataType currentDataType;    int numBytesForCurrentDataType;    int transferTimerId;    bool isGreetingMessageSent;};#endif连接的实现软件的重点:面向连接。 Connect.cpp#include "connection.h"#include <QtNetwork>static const int TransferTimeout = 30 * 1000;static const int PongTimeout = 60 * 1000;static const int PingInterval = 5 * 1000;static const char SeparatorToken = ' ';Connection::Connection(QObject *parent)    : QTcpSocket(parent){    greetingMessage = tr("undefined");    username = tr("unknown");    state = WaitingForGreeting;    currentDataType = Undefined;    numBytesForCurrentDataType = -1;    transferTimerId = 0;    isGreetingMessageSent = false;    pingTimer.setInterval(PingInterval);    QObject::connect(this, SIGNAL(readyRead()), this, SLOT(processReadyRead()));    QObject::connect(this, SIGNAL(disconnected()), &pingTimer, SLOT(stop()));    QObject::connect(&pingTimer, SIGNAL(timeout()), this, SLOT(sendPing()));    QObject::connect(this, SIGNAL(connected()),                     this, SLOT(sendGreetingMessage()));}QString Connection::name() const{    return username;}void Connection::setGreetingMessage(const QString &message){    greetingMessage = message;}bool Connection::sendMessage(const QString &message){    if (message.isEmpty())        return false;    QByteArray msg = message.toUtf8();    QByteArray data = "MESSAGE " + QByteArray::number(msg.size()) + ' ' + msg;    return write(data) == data.size();}void Connection::timerEvent(QTimerEvent *timerEvent){    if (timerEvent->timerId() == transferTimerId) {        abort();        killTimer(transferTimerId);        transferTimerId = 0;    }}void Connection::processReadyRead(){    if (state == WaitingForGreeting) {        if (!readProtocolHeader())            return;        if (currentDataType != Greeting) {            abort();            return;        }        state = ReadingGreeting;    }    if (state == ReadingGreeting) {        if (!hasEnoughData())            return;        buffer = read(numBytesForCurrentDataType);        if (buffer.size() != numBytesForCurrentDataType) {            abort();            return;        }        username = QString(buffer) + '@' + peerAddress().toString() + ':'                   + QString::number(peerPort());        currentDataType = Undefined;        numBytesForCurrentDataType = 0;        buffer.clear();        if (!isValid()) {            abort();            return;        }        if (!isGreetingMessageSent)            sendGreetingMessage();        pingTimer.start();        pongTime.start();        state = ReadyForUse;        emit readyForUse();    }    do {        if (currentDataType == Undefined) {            if (!readProtocolHeader())                return;        }        if (!hasEnoughData())            return;        processData();    } while (bytesAvailable() > 0);}void Connection::sendPing(){    if (pongTime.elapsed() > PongTimeout) {        abort();        return;    }    write("PING 1 p");}void Connection::sendGreetingMessage(){    QByteArray greeting = greetingMessage.toUtf8();    QByteArray data = "GREETING " + QByteArray::number(greeting.size()) + ' ' + greeting;    if (write(data) == data.size())        isGreetingMessageSent = true;}int Connection::readDataIntoBuffer(int maxSize){    if (maxSize > MaxBufferSize)        return 0;    int numBytesBeforeRead = buffer.size();    if (numBytesBeforeRead == MaxBufferSize) {        abort();        return 0;    }    while (bytesAvailable() > 0 && buffer.size() < maxSize) {        buffer.append(read(1));        if (buffer.endsWith(SeparatorToken))            break;    }    return buffer.size() - numBytesBeforeRead;}int Connection::dataLengthForCurrentDataType(){    if (bytesAvailable() <= 0 || readDataIntoBuffer() <= 0            || !buffer.endsWith(SeparatorToken))        return 0;    buffer.chop(1);    int number = buffer.toInt();    buffer.clear();    return number;}bool Connection::readProtocolHeader(){    if (transferTimerId) {        killTimer(transferTimerId);        transferTimerId = 0;    }    if (readDataIntoBuffer() <= 0) {        transferTimerId = startTimer(TransferTimeout);        return false;    }    if (buffer == "PING ") {        currentDataType = Ping;    } else if (buffer == "PONG ") {        currentDataType = Pong;    } else if (buffer == "MESSAGE ") {        currentDataType = PlainText;    } else if (buffer == "GREETING ") {        currentDataType = Greeting;    } else {        currentDataType = Undefined;        abort();        return false;    }    buffer.clear();    numBytesForCurrentDataType = dataLengthForCurrentDataType();    return true;}bool Connection::hasEnoughData(){    if (transferTimerId) {        QObject::killTimer(transferTimerId);        transferTimerId = 0;    }    if (numBytesForCurrentDataType <= 0)        numBytesForCurrentDataType = dataLengthForCurrentDataType();    if (bytesAvailable() < numBytesForCurrentDataType            || numBytesForCurrentDataType <= 0) {        transferTimerId = startTimer(TransferTimeout);        return false;    }    return true;}void Connection::processData(){    buffer = read(numBytesForCurrentDataType);    if (buffer.size() != numBytesForCurrentDataType) {        abort();        return;    }    switch (currentDataType) {    case PlainText:        emit newMessage(username, QString::fromUtf8(buffer));        break;    case Ping:        write("PONG 1 p");        break;    case Pong:        pongTime.restart();        break;    default:        break;    }    currentDataType = Undefined;    numBytesForCurrentDataType = 0;    buffer.clear();}网路频宽管理伺服器定义软件的重点,connection连接好后便会调用peermanager进行传输。真正帧的封装交给了库函数,这儿只是运用了类似于帧的封装的封装信息处理。Peermanager.h#ifndef PEERMANAGER_H#define PEERMANAGER_H#include <QByteArray>#include <QList>#include <QObject>#include <QTimer>#include <QUdpSocket>class Client;class Connection;class PeerManager : public QObject{    Q_OBJECTpublic:    PeerManager(Client *client);    void setServerPort(int port);    QByteArray userName() const;    void startBroadcasting();    bool isLocalHostAddress(const QHostAddress &address);signals:    void newConnection(Connection *connection);private slots:    void sendBroadcastDatagram();    void readBroadcastDatagram();private:    void updateAddresses();    Client *client;    QList<QHostAddress> broadcastAddresses;    QList<QHostAddress> ipAddresses;    QUdpSocket broadcastSocket;    QTimer broadcastTimer;    QByteArray username;    int serverPort;};#endifPeermanager.cpp#include <QtNetwork>#include "client.h"#include "connection.h"#include "peermanager.h"static const qint32 BroadcastInterval = 2000;static const unsigned broadcastPort = 45000;PeerManager::PeerManager(Client *client)    : QObject(client){    this->client = client;    QStringList envVariables;    envVariables << "USERNAME.*" << "USER.*" << "USERDOMAIN.*"                 << "HOSTNAME.*" << "DOMAINNAME.*";    QStringList environment = QProcess::systemEnvironment();    foreach (QString string, envVariables) {        int index = environment.indexOf(QRegExp(string));        if (index != -1) {            QStringList stringList = environment.at(index).split('=');            if (stringList.size() == 2) {                username = stringList.at(1).toUtf8();                break;            }        }    }    if (username.isEmpty())        username = "unknown";    updateAddresses();    serverPort = 0;    broadcastSocket.bind(QHostAddress::Any, broadcastPort, QUdpSocket::ShareAddress                         | QUdpSocket::ReuseAddressHint);    connect(&broadcastSocket, SIGNAL(readyRead()),            this, SLOT(readBroadcastDatagram()));    broadcastTimer.setInterval(BroadcastInterval);    connect(&broadcastTimer, SIGNAL(timeout()),            this, SLOT(sendBroadcastDatagram()));}void PeerManager::setServerPort(int port){    serverPort = port;}QByteArray PeerManager::userName() const{    return username;}void PeerManager::startBroadcasting(){    broadcastTimer.start();}bool PeerManager::isLocalHostAddress(const QHostAddress &address){    foreach (QHostAddress localAddress, ipAddresses) {        if (address == localAddress)            return true;    }    return false;}void PeerManager::sendBroadcastDatagram(){    QByteArray datagram(username);    datagram.append('@');    datagram.append(QByteArray::number(serverPort));    bool validBroadcastAddresses = true;    foreach (QHostAddress address, broadcastAddresses) {        if (broadcastSocket.writeDatagram(datagram, address,                                          broadcastPort) == -1)            validBroadcastAddresses = false;    }    if (!validBroadcastAddresses)        updateAddresses();}void PeerManager::readBroadcastDatagram(){    while (broadcastSocket.hasPendingDatagrams()) {        QHostAddress senderIp;        quint16 senderPort;        QByteArray datagram;        datagram.resize(broadcastSocket.pendingDatagramSize());        if (broadcastSocket.readDatagram(datagram.data(), datagram.size(),                                         &senderIp, &senderPort) == -1)            continue;        QList<QByteArray> list = datagram.split('@');        if (list.size() != 2)            continue;        int senderServerPort = list.at(1).toInt();        if (isLocalHostAddress(senderIp) && senderServerPort == serverPort)            continue;        if (!client->hasConnection(senderIp)) {            Connection *connection = new Connection(this);            emit newConnection(connection);            connection->connectToHost(senderIp, senderServerPort);        }    }}void PeerManager::updateAddresses(){    broadcastAddresses.clear();    ipAddresses.clear();    foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) {        foreach (QNetworkAddressEntry entry, interface.addressEntries()) {            QHostAddress broadcastAddress = entry.broadcast();            if (broadcastAddress != QHostAddress::Null && entry.ip() != QHostAddress::LocalHost) {                broadcastAddresses << broadcastAddress;                ipAddresses << entry.ip();            }        }    }}服务器定义Server.h#ifndef SERVER_H#define SERVER_H#include <QTcpServer>class Connection;class Server : public QTcpServer{    Q_OBJECTpublic:    Server(QObject *parent = 0);signals:    void newConnection(Connection *connection);protected:    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;};#endifServer.cpp#include <QtNetwork>#include "connection.h"#include "server.h"Server::Server(QObject *parent)    : QTcpServer(parent){    listen(QHostAddress::Any);}void Server::incomingConnection(qintptr socketDescriptor){    Connection *connection = new Connection(this);    connection->setSocketDescriptor(socketDescriptor);    emit newConnection(connection);}<span style="white-space:pre"></span>首先是工程</p><p><span style="white-space:pre"></span>network-chat.pro</p><p></p><pre name="code" class="cpp">HEADERS       = chatdialog.h \
                client.h \
                connection.h \
                peermanager.h \
                server.h
SOURCES       = chatdialog.cpp \
                client.cpp \
                connection.cpp \
                main.cpp \
                peermanager.cpp \
                server.cpp
FORMS         = chatdialog.ui
QT           += network widgets

# install
target.path = $$[QT_INSTALL_EXAMPLES]/network/network-chat
INSTALLS += target

和普通的qmake文件没什么太大区别,注意要加上 QT += network widgets ,只有加上这个QT 才能有网络库。

接下来是整个界面的定义,

chatdialog.h

#ifndef CHATDIALOG_H
#define CHATDIALOG_H

#include "ui_chatdialog.h"
#include "client.h"

class ChatDialog : public QDialog, private Ui::ChatDialog
{
    Q_OBJECT

public:
    ChatDialog(QWidget *parent = 0);

public slots:
    void appendMessage(const QString &from, const QString &message);

private slots:
    void returnPressed();
    void newParticipant(const QString &nick);
    void participantLeft(const QString &nick);
    void showInformation();

private:
    Client client;
    QString myNickName;
    QTextTableFormat tableFormat;
};

#endif


然后是界面的实现

chatdialog.cpp

#include <QtWidgets>

#include "chatdialog.h"

ChatDialog::ChatDialog(QWidget *parent)
    : QDialog(parent)
{
    setupUi(this);

    lineEdit->setFocusPolicy(Qt::StrongFocus);<span style="white-space:pre">			</span>//将光标锁定在lineEdit
    textEdit->setFocusPolicy(Qt::NoFocus);<span style="white-space:pre">			</span>//光标不会出现在textedit,listwidget
    textEdit->setReadOnly(true);<span style="white-space:pre">				</span>
    listWidget->setFocusPolicy(Qt::NoFocus);

    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
    connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
    connect(&client, SIGNAL(newMessage(QString,QString)),
            this, SLOT(appendMessage(QString,QString)));
    connect(&client, SIGNAL(newParticipant(QString)),
            this, SLOT(newParticipant(QString)));
    connect(&client, SIGNAL(participantLeft(QString)),
            this, SLOT(participantLeft(QString)));

    myNickName = client.nickName();<span style="white-space:pre">				</span>//返回用户名,nickName()是自己定义的一个函数
    newParticipant(myNickName);<span style="white-space:pre">					</span>
    tableFormat.setBorder(0);<span style="white-space:pre">					</span>//设置界面边沿宽度为0
    QTimer::singleShot(10 * 1000, this, SLOT(showInformation()));<span style="white-space:pre">	</span>//程序在10秒后会调用一个槽showInformation()
}

void ChatDialog::appendMessage(const QString &from, const QString &message)
{
    if (from.isEmpty() || message.isEmpty())
        return;

    QTextCursor cursor(textEdit->textCursor());
    cursor.movePosition(QTextCursor::End);<span style="white-space:pre">			</span>//将textEdit里的光标设置在文字的最后,以免输出混乱
    QTextTable *table = cursor.insertTable(1, 2, tableFormat);<span style="white-space:pre">	</span>
    table->cellAt(0, 0).firstCursorPosition().insertText('<' + from + "> ");
    table->cellAt(0, 1).firstCursorPosition().insertText(message);<span style="white-space:pre">		</span><span style="font-family: Arial, Helvetica, sans-serif;">//设置textEdit的输出格式</span>
    QScrollBar *bar = textEdit->verticalScrollBar();<span style="white-space:pre">		</span>//设置textEdit支持垂直滚动
    bar->setValue(bar->maximum());
}

void ChatDialog::returnPressed()
{
    QString text = lineEdit->text();
    if (text.isEmpty())
        return;

    if (text.startsWith(QChar('/'))) {<span style="white-space:pre">		</span>//输入以"/"打头的字符会报错
        QColor color = textEdit->textColor();
        textEdit->setTextColor(Qt::red);<span style="white-space:pre">	</span>//报错内容为红色
        textEdit->append(tr("! Unknown command: %1")
                         .arg(text.left(text.indexOf(' '))));
        textEdit->setTextColor(color);<span style="white-space:pre">		</span>//将输出内容重新设为黑色
    } else {
        client.sendMessage(text);<span style="white-space:pre">		</span>//发送给客户机文本信息
        appendMessage(myNickName, text);<span style="white-space:pre">	</span>//在本机上显示文本信息
    }

    lineEdit->clear();
}


void ChatDialog::newParticipant(const QString &nick)
{
    if (nick.isEmpty())
        return;

    QColor color = textEdit->textColor();
    textEdit->setTextColor(Qt::gray);<span style="white-space:pre">		</span>//将加入者信息输出设为灰色
    textEdit->append(tr("* %1 has joined").arg(nick));
    textEdit->setTextColor(color);<span style="white-space:pre">		</span>//重设为黑色
    listWidget->addItem(nick);<span style="white-space:pre">			</span>//在listWidget栏内添加新的成员
}
void ChatDialog::participantLeft(const QString &nick)
{
    if (nick.isEmpty())
        return;

    QList<QListWidgetItem *> items = listWidget->findItems(nick,
                                                           Qt::MatchExactly);<span style="white-space:pre">	</span>//在listWidget栏中找到离开者的项
    if (items.isEmpty())<span style="white-space:pre">	</span>
        return;

    delete items.at(0);<span style="white-space:pre">				</span>//删除项
    QColor color = textEdit->textColor();
    textEdit->setTextColor(Qt::gray);<span style="white-space:pre">		</span>//输出相应信息
    textEdit->append(tr("* %1 has left").arg(nick));
    textEdit->setTextColor(color);
}
void ChatDialog::showInformation()
{
    if (listWidget->count() == 1) {<span style="white-space:pre">		</span>//十秒后输出的信息
        QMessageBox::information(this, tr("Chat"),
                                 tr("Launch several instances of this "
                                    "program on your local network and "
                                    "start chatting!"));
    }
}








评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值