基于QT 局域网聊天工具实现

实现较简单,主要就四个类:
widget     主窗口,群聊,发送文件,
Tcpclient  接收文件
Tcpserver  发送文件
Chat  建立私聊



Widget >> setupUi
Widget >> new TcpServer
Widget >> sendMessage(NewParticipant)
Widget >> new QUdpSocket
Widget >> tableWidget_doubleClicked >> new Chat
Widget >> bind(udpSocket) >> connet(udpSocket, processPending)
  processPending >> NewParticipant >> add new(判断是否已有) >> sendMessage(NewParticipant )(回应)
  processPending >> ParticipantLeft >> release partner
  processPending >> new chat(name,ip) >> showChat
  processPending >> Message >> ui->textBrowser->append(message)
  processPending >> FileName >> hasPendingFile >> QMessageBox::information >> yes >>new TcpClient
                                            QMessageBox::information >> refuse >> send
  processPending >> Refuse >> tcpServer->close()


TcpServer >> setupUi
TcpServer >> Send_clicked >> emit sendFileName(theFileName) >> sendMessage




Tcpclient >> setupUi
Tcpclient >> connect(readyRead(),readMessage())
Tcpclient >> connect(SocketError(),SocketError())


Chat >> setupUi
Chat >> new QUdpSocket >> bind >> connect(readyRead(),PendingData()) //the same as Widget
Chat >> new TcpServer //the same as Widget



main.c

#include 
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    w.show();
    return a.exec();
}


Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include "tcpclient.h"
#include "tcpserver.h"
#include "chat.h"
using namespace std::tr1;
namespace Ui {
    class Widget;
}

//enum MessageType
//{
//    Message,
//    NewParticipant,
//    ParticipantLeft,
//    FileName,
//    Refuse,
//    xchat
//};

//枚举变量标志信息的类型,分别为消息,新用户加入,和用户退出
class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    QString getUserName();
    QString getMessage();
	chat* privatechat;
	chat* privatechat1;

protected:
    void changeEvent(QEvent *e);
    void sendMessage(MessageType type,QString serverAddress="");
    void newParticipant(QString userName,QString localHostName,QString ipAddress);
    void participantLeft(QString userName,QString localHostName,QString time);
    void closeEvent(QCloseEvent *);
    void hasPendingFile(QString userName,QString serverAddress,
                        QString clientAddress,QString fileName);

     bool eventFilter(QObject *target, QEvent *event);//事件过滤器
private:
    Ui::Widget *ui;
    QUdpSocket *udpSocket;
    qint32 port;
	qint32 bb;
    QString fileName;
    TcpServer *server;
    //chat *privatechat;

    QString getIP();

    QColor color;//颜色

    bool saveFile(const QString& fileName);//保存聊天记录
    void showxchat(QString name, QString ip);

private slots:
    void on_tableWidget_doubleClicked(QModelIndex index);
    void on_textUnderline_clicked(bool checked);
    void on_clear_clicked();
    void on_save_clicked();
    void on_textcolor_clicked();
    void on_textitalic_clicked(bool checked);
    void on_textbold_clicked(bool checked);
    void on_fontComboBox_currentFontChanged(QFont f);
    void on_fontsizecomboBox_currentIndexChanged(QString );
    void on_close_clicked();
    void on_sendfile_clicked();
    void on_send_clicked();
    void processPendingDatagrams();
    void sentFileName(QString);
    void currentFormatChanged(const QTextCharFormat &format);

signals:


};

#endif // WIDGET_H

widget.c

#include "widget.h"
#include "ui_widget.h"
using namespace std::tr1;
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);   
    this->resize(850,550);
    ui->textEdit->setFocusPolicy(Qt::StrongFocus);
    ui->textBrowser->setFocusPolicy(Qt::NoFocus);

    ui->textEdit->setFocus();
    ui->textEdit->installEventFilter(this);//设置完后自动调用其eventFilter函数
	privatechat = NULL;
	privatechat1 = NULL;

    udpSocket = new QUdpSocket(this);
    port = 45454;
	bb = 0;
    udpSocket->bind(port,QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
    sendMessage(NewParticipant);

    server = new TcpServer(this);
    connect(server,SIGNAL(sendFileName(QString)),this,SLOT(sentFileName(QString)));
    connect(ui->textEdit,SIGNAL(currentCharFormatChanged(QTextCharFormat)),this,SLOT(currentFormatChanged(const QTextCharFormat)));

}

void Widget::currentFormatChanged(const QTextCharFormat &format)
{//当编辑器的字体格式改变时,我们让部件状态也随之改变
    ui->fontComboBox->setCurrentFont(format.font());

    if(format.fontPointSize()<9)  //如果字体大小出错,因为我们最小的字体为9
    {
        ui->fontsizecomboBox->setCurrentIndex(3); //即显示12
    }
    else
    {
        ui->fontsizecomboBox->setCurrentIndex(ui->fontsizecomboBox->findText(QString::number(format.fontPointSize())));

    }

    ui->textbold->setChecked(format.font().bold());
    ui->textitalic->setChecked(format.font().italic());
    ui->textUnderline->setChecked(format.font().underline());
    color = format.foreground().color();
}

void Widget::processPendingDatagrams()   //接收数据UDP
{
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());
        QDataStream in(&datagram,QIODevice::ReadOnly);
        int messageType;
        in >> messageType;
        QString userName,localHostName,ipAddress,message;
        QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        switch(messageType)
        {
            case Message:
                {
                    in >>userName >>localHostName >>ipAddress >>message;
                    ui->textBrowser->setTextColor(Qt::blue);
                    ui->textBrowser->setCurrentFont(QFont("Times New Roman",12));
                    ui->textBrowser->append("[ " +localHostName+" ] "+ time);
                    ui->textBrowser->append(message);
                    break;
                }
            case NewParticipant:
                {
                    in >>userName >>localHostName >>ipAddress;
                    newParticipant(userName,localHostName,ipAddress);

                    break;
                }
            case ParticipantLeft:
                {
                    in >>userName >>localHostName;
                    participantLeft(userName,localHostName,time);
                    break;
                }
        case FileName:
            {
                in >>userName >>localHostName >> ipAddress;
                QString clientAddress,fileName;
                in >> clientAddress >> fileName;
                hasPendingFile(userName,ipAddress,clientAddress,fileName);
                break;
            }
        case Refuse:
            {
                in >> userName >> localHostName;
                QString serverAddress;
                in >> serverAddress;            
                QString ipAddress = getIP();

                if(ipAddress == serverAddress)
                {
                    server->refused();
                }
                break;
            }
        case Xchat:
            {
                in >>userName >>localHostName >>ipAddress;
                showxchat(localHostName,ipAddress);//显示与主机名聊天中,不是用户名
                break;
            }
        }
    }
}

//处理新用户加入
void Widget::newParticipant(QString userName,QString localHostName,QString ipAddress)
{
    bool bb = ui->tableWidget->findItems(localHostName,Qt::MatchExactly).isEmpty();
    if(bb)
    {
        QTableWidgetItem *user = new QTableWidgetItem(userName);
        QTableWidgetItem *host = new QTableWidgetItem(localHostName);
        QTableWidgetItem *ip = new QTableWidgetItem(ipAddress);
        ui->tableWidget->insertRow(0);
        ui->tableWidget->setItem(0,0,user);
        ui->tableWidget->setItem(0,1,host);
        ui->tableWidget->setItem(0,2,ip);
        ui->textBrowser->setTextColor(Qt::gray);
        ui->textBrowser->setCurrentFont(QFont("Times New Roman",10));
        ui->textBrowser->append(tr("%1 在线!").arg(localHostName));
        ui->onlineUser->setText(tr("在线人数:%1").arg(ui->tableWidget->rowCount()));
        sendMessage(NewParticipant);
    }
}

//处理用户离开
void Widget::participantLeft(QString userName,QString localHostName,QString time)
{
    int rowNum = ui->tableWidget->findItems(localHostName,Qt::MatchExactly).first()->row();
    ui->tableWidget->removeRow(rowNum);
    ui->textBrowser->setTextColor(Qt::gray);
    ui->textBrowser->setCurrentFont(QFont("Times New Roman",10));
    ui->textBrowser->append(tr("%1 于 %2 离开!").arg(localHostName).arg(time));
    ui->onlineUser->setText(tr("在线人数:%1").arg(ui->tableWidget->rowCount()));
}

Widget::~Widget()
{
    delete ui;
//	delete privatechat;
//	privatechat = NULL;
	//udpSocket
	//server
}

void Widget::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

QString Widget::getIP()  //获取ip地址
{
    QList list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
       if(address.protocol() == QAbstractSocket::IPv4Protocol) //我们使用IPv4地址
            return address.toString();
    }
       return 0;
}

void Widget::sendMessage(MessageType type, QString serverAddress)  //发送信息
{
    QByteArray data;
    QDataStream out(&data,QIODevice::WriteOnly);
    QString localHostName = QHostInfo::localHostName();
    QString address = getIP();
    out << type << getUserName() << localHostName;


    switch(type)
    {
        case ParticipantLeft:
            {
                break;
            }
        case NewParticipant:
            {         
                out << address;
                break;
            }

        case Message :
            {
                if(ui->textEdit->toPlainText() == "")
                {
                    QMessageBox::warning(0,tr("警告"),tr("发送内容不能为空"),QMessageBox::Ok);
                    return;
                }
               out << address << getMessage();
               ui->textBrowser->verticalScrollBar()->setValue(ui->textBrowser->verticalScrollBar()->maximum());
               break;

            }
        case FileName:
            {
                int row = ui->tableWidget->currentRow();
                QString clientAddress = ui->tableWidget->item(row,2)->text();
                out << address << clientAddress << fileName;
                break;
            }
        case Refuse:
            {
                out << serverAddress;
                break;
            }
    }
    udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast, port);

}

QString Widget::getUserName()  //获取用户名
{
    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)
            {
                return stringList.at(1);
                break;
            }
        }
    }
    return false;
}

QString Widget::getMessage()  //获得要发送的信息
{
    QString msg = ui->textEdit->toHtml();

    ui->textEdit->clear();
    ui->textEdit->setFocus();
    return msg;
}

void Widget::closeEvent(QCloseEvent *)
{
    sendMessage(ParticipantLeft);
}

void Widget::sentFileName(QString fileName)
{
    this->fileName = fileName;
    sendMessage(FileName);
}

void Widget::hasPendingFile(QString userName,QString serverAddress,  //接收文件
                            QString clientAddress,QString fileName)
{
    QString ipAddress = getIP();
    if(ipAddress == clientAddress)
    {
        int btn = QMessageBox::information(this,tr("接受文件"),
                                 tr("来自%1(%2)的文件:%3,是否接收?")
                                 .arg(userName).arg(serverAddress).arg(fileName),
                                 QMessageBox::Yes,QMessageBox::No);
        if(btn == QMessageBox::Yes)
        {
            QString name = QFileDialog::getSaveFileName(0,tr("保存文件"),fileName);
            if(!name.isEmpty())
            {
                TcpClient *client = new TcpClient(this);
                client->setFileName(name);
                client->setHostAddress(QHostAddress(serverAddress));
                client->show();

            }

        }
        else{
            sendMessage(Refuse,serverAddress);
        }
    }
}

void Widget::on_send_clicked()//发送
{
    sendMessage(Message);
}

void Widget::on_sendfile_clicked()
{
    if(ui->tableWidget->selectedItems().isEmpty())
    {
        QMessageBox::warning(0,tr("选择用户"),tr("请先从用户列表选择要传送的用户!"),QMessageBox::Ok);
        return;
    }
    server->show();
    server->initServer();
}

void Widget::on_close_clicked()//关闭
{
    this->close();
}

bool Widget::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->textEdit)
    {
        if(event->type() == QEvent::KeyPress)//回车键
        {
             QKeyEvent *k = static_cast(event);
             if(k->key() == Qt::Key_Return)
             {
                 on_send_clicked();
                 return true;
             }
        }
    }
    return QWidget::eventFilter(target,event);
}

void Widget::on_fontComboBox_currentFontChanged(QFont f)//字体设置
{
    ui->textEdit->setCurrentFont(f);
    ui->textEdit->setFocus();
}

//字体大小设置
void Widget::on_fontsizecomboBox_currentIndexChanged(QString size)
{
   ui->textEdit->setFontPointSize(size.toDouble());
   ui->textEdit->setFocus();
}

void Widget::on_textbold_clicked(bool checked)
{
    if(checked)
        ui->textEdit->setFontWeight(QFont::Bold);
    else
        ui->textEdit->setFontWeight(QFont::Normal);
    ui->textEdit->setFocus();
}

void Widget::on_textitalic_clicked(bool checked)
{
    ui->textEdit->setFontItalic(checked);
    ui->textEdit->setFocus();
}

void Widget::on_textUnderline_clicked(bool checked)
{
    ui->textEdit->setFontUnderline(checked);
    ui->textEdit->setFocus();
}

void Widget::on_textcolor_clicked()
{
    color = QColorDialog::getColor(color,this);
    if(color.isValid())
    {
        ui->textEdit->setTextColor(color);
        ui->textEdit->setFocus();
    }
}

void Widget::on_save_clicked()//保存聊天记录
{
    if(ui->textBrowser->document()->isEmpty())
        QMessageBox::warning(0,tr("警告"),tr("聊天记录为空,无法保存!"),QMessageBox::Ok);
    else
    {
       //获得文件名,注意getSaveFileName函数的格式即可
       QString fileName = QFileDialog::getSaveFileName(this,tr("保存聊天记录"),tr("聊天记录"),tr("文本(*.txt);;All File(*.*)"));
       if(!fileName.isEmpty())
           saveFile(fileName);
    }
}

bool Widget::saveFile(const QString &fileName)//保存文件
{
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly | QFile::Text))

    {
        QMessageBox::warning(this,tr("保存文件"),
        tr("无法保存文件 %1:\n %2").arg(fileName)
        .arg(file.errorString()));
        return false;
    }
    QTextStream out(&file);
    out << ui->textBrowser->toPlainText();

    return true;
}

void Widget::on_clear_clicked()//清空聊天记录
{
    ui->textBrowser->clear();
}


void Widget::on_tableWidget_doubleClicked(QModelIndex index)
{
	if(ui->tableWidget->item(index.row(),0)->text() == getUserName() &&
		ui->tableWidget->item(index.row(),2)->text() == getIP())
	{
		QMessageBox::warning(0,tr("警告"),tr("你不可以跟自己聊天!!!"),QMessageBox::Ok);
	}
	else
    {
	//	else
		if(!privatechat){
      //  chat *privatechatTemp;
		privatechat = new chat(ui->tableWidget->item(index.row(),1)->text(), //接收主机名
                               ui->tableWidget->item(index.row(),2)->text()) ;//接收用户IP
		}
//		if( privatechat->is_opened )delete privatechat;//如果其曾经显示过则删除掉
        QByteArray data;
        QDataStream out(&data,QIODevice::WriteOnly);
        QString localHostName = QHostInfo::localHostName();
        QString address = getIP();
        out << Xchat << getUserName() << localHostName << address;
        udpSocket->writeDatagram(data,data.length(),QHostAddress::QHostAddress(ui->tableWidget->item(index.row(),2)->text()), port);

//		privatechat->xchat->writeDatagram(data,data.length(),QHostAddress::QHostAddress(ui->tableWidget->item(index.row(),2)->text()), 45456);
      //  if(!privatechat->is_opened)
			privatechat->show();
		privatechat->is_opened = true;
	//	(privatechat->a) = 0;
    }

}

void Widget::showxchat(QString name, QString ip)
{
//	if(!privatechat){
 // chat *privatechatTemp;
	if(!privatechat1)
	privatechat1 = new chat(name,ip);
//	privatechat = privatechatTemp;}
//	chat privatechat(name,ip);//如果不用new函数,则程序运行时只是闪烁显示一下就没了,因为类的生命周期结束了
//	privatechat->is_opened = false;
 // privatechat->show();
  //privatechat.textBrowser.show();
  //privatechat->is_opened = true;
	bb++;
	//delete privatechat;

}


tcpserve.h

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include 
#include 
#include 
#include 

namespace Ui {
    class TcpServer;
}

class TcpServer : public QDialog
{
    Q_OBJECT

public:
    explicit TcpServer(QWidget *parent = 0);
    ~TcpServer();
    void refused();

    void initServer();


protected:
    void changeEvent(QEvent *e);

private:
    Ui::TcpServer *ui;
    qint16 tcpPort;
    QTcpServer *tcpServer;
    QString fileName;
    QString theFileName;
    QFile *localFile;

    qint64 TotalBytes;
    qint64 bytesWritten;
    qint64 bytesToWrite;
    qint64 loadSize;
    QByteArray outBlock;//缓存一次发送的数据

    QTcpSocket *clientConnection;

    QTime time;//计时器

private slots:
    void on_serverSendBtn_clicked();
    void on_serverCloseBtn_clicked();
    void on_serverOpenBtn_clicked();
    void sendMessage();

   void updateClientProgress(qint64 numBytes);
signals:
    void sendFileName(QString fileName);

};

#endif // TCPSERVER_H


tcpserve.c
#include "tcpserver.h"
#include "ui_tcpserver.h"
#include 
#include 
#include 

TcpServer::TcpServer(QWidget *parent):QDialog(parent),
 ui(new Ui::TcpServer)
{
    ui->setupUi(this);
    this->setFixedSize(350,180);

    tcpPort = 6666;
    tcpServer = new QTcpServer(this);  
    connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage()));

    initServer();

}

TcpServer::~TcpServer()
{
    delete ui;
}

void TcpServer::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void TcpServer::sendMessage()  //开始发送数据
{
    ui->serverSendBtn->setEnabled(false);
    clientConnection = tcpServer->nextPendingConnection();
    connect(clientConnection,SIGNAL(bytesWritten(qint64)),SLOT(updateClientProgress(qint64)));

    ui->serverStatusLabel->setText(tr("开始传送文件 %1 !").arg(theFileName));

    localFile = new QFile(fileName);
    if(!localFile->open((QFile::ReadOnly))){//以只读方式打开
        QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件 %1:\n%2").arg(fileName).arg(localFile->errorString()));
        return;
    }
    TotalBytes = localFile->size();
    QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
    sendOut.setVersion(QDataStream::Qt_4_6);
    time.start();  //开始计时
    QString currentFile = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
    sendOut<seek(0);
    sendOut<write(outBlock);
    qDebug()< 0){
        outBlock = localFile->read(qMin(bytesToWrite,loadSize));
        bytesToWrite -= (int)clientConnection->write(outBlock);
        outBlock.resize(0);
    }
    else{
        localFile->close();
    }
    ui->progressBar->setMaximum(TotalBytes);
    ui->progressBar->setValue(bytesWritten);

   float useTime = time.elapsed();
   double speed = bytesWritten / useTime;
   ui->serverStatusLabel->setText(tr("已发送 %1MB (%2MB/s) \n共%3MB 已用时:%4秒\n估计剩余时间:%5秒")
                                  .arg(bytesWritten / (1024*1024))//已发送
                                  .arg(speed*1000/(1024*1024),0,'f',2)//速度
                                  .arg(TotalBytes / (1024 * 1024))//总大小
                                  .arg(useTime/1000,0,'f',0)//用时
                                  .arg(TotalBytes/speed/1000 - useTime/1000,0,'f',0));//剩余时间

   //num.sprintf("%.1f KB/s", (bytesWritten*1000) / (1024.0*time.elapsed()));
    if(bytesWritten == TotalBytes)
        ui->serverStatusLabel->setText(tr("传送文件 %1 成功").arg(theFileName));

}

void TcpServer::on_serverOpenBtn_clicked()  //打开
{
    fileName = QFileDialog::getOpenFileName(this);
    if(!fileName.isEmpty())
    {
        theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
        ui->serverStatusLabel->setText(tr("要传送的文件为:%1 ").arg(theFileName));
        ui->serverSendBtn->setEnabled(true);
        ui->serverOpenBtn->setEnabled(false);
    }
}

void TcpServer::refused()   //被对方拒绝
{
    tcpServer->close();
    ui->serverStatusLabel->setText(tr("对方拒绝接收!!!"));
}

void TcpServer::on_serverSendBtn_clicked()  //发送
{
    if(!tcpServer->listen(QHostAddress::Any,tcpPort))//开始监听
    {
        qDebug() << tcpServer->errorString();
        close();
        return;
    }

    ui->serverStatusLabel->setText(tr("等待对方接收... ..."));
    emit sendFileName(theFileName);
}

void TcpServer::on_serverCloseBtn_clicked()//退出
{   
    if(tcpServer->isListening())
    {
        tcpServer->close();
        clientConnection->abort();
    }
    this->close();
}

void TcpServer::initServer()//初始化
{
    loadSize = 4*1024;
    TotalBytes = 0;
    bytesWritten = 0;
    bytesToWrite = 0;

    ui->serverStatusLabel->setText(tr("请选择要传送的文件"));
    ui->progressBar->reset();
    ui->serverOpenBtn->setEnabled(true);
    ui->serverSendBtn->setEnabled(false);

    tcpServer->close();

}


tcpclient.h

#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include 
#include 
#include 
#include 
#include 
namespace Ui {
    class TcpClient;
}

class TcpClient : public QDialog
{
    Q_OBJECT

public:
    explicit TcpClient(QWidget *parent = 0);
    ~TcpClient();
    void setHostAddress(QHostAddress address);
    void setFileName(QString fileName){localFile = new QFile(fileName);}

protected:
    void changeEvent(QEvent *e);

private:
    Ui::TcpClient *ui;
    QTcpSocket *tcpClient;
    quint16 blockSize;
    QHostAddress hostAddress;
    qint16 tcpPort;

    qint64 TotalBytes;
    qint64 bytesReceived;
    qint64 bytesToReceive;
    qint64 fileNameSize;
    QString fileName;
    QFile *localFile;
    QByteArray inBlock;

    QTime time;

private slots:
    void on_tcpClientCancleBtn_clicked();
    void on_tcpClientCloseBtn_clicked();
    void newConnect();
    void readMessage();
    void displayError(QAbstractSocket::SocketError);
};

#endif // TCPCLIENT_H

tcpclient.c

#include "tcpclient.h"
#include "ui_tcpclient.h"
#include 
#include 
TcpClient::TcpClient(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpClient)
{
    ui->setupUi(this);
    this->setFixedSize(350,180);

    TotalBytes = 0;
    bytesReceived = 0;
    fileNameSize = 0;

    tcpClient = new QTcpSocket(this);
    tcpPort = 6666;
    connect(tcpClient,SIGNAL(readyRead()),this,SLOT(readMessage()));
    connect(tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,
            SLOT(displayError(QAbstractSocket::SocketError)));

}

TcpClient::~TcpClient()
{
    delete ui;
}

void TcpClient::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void TcpClient::setHostAddress(QHostAddress address)  //设置服务器地址并连接服务器
{
    hostAddress = address;
    newConnect();
}
void TcpClient::newConnect()
{
    blockSize = 0;
    tcpClient->abort();
    tcpClient->connectToHost(hostAddress,tcpPort);
    time.start();
}

void TcpClient::readMessage()
{
    QDataStream in(tcpClient);
    in.setVersion(QDataStream::Qt_4_6);

    float useTime = time.elapsed();
    if(bytesReceived <= sizeof(qint64)*2){
        if((tcpClient->bytesAvailable() >= sizeof(qint64)*2) && (fileNameSize == 0)){
            in>>TotalBytes>>fileNameSize;
            bytesReceived += sizeof(qint64)*2;
        }
        if((tcpClient->bytesAvailable() >= fileNameSize) && (fileNameSize != 0)){
            in>>fileName;
            bytesReceived +=fileNameSize;

            if(!localFile->open(QFile::WriteOnly)){
                QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件 %1:\n%2.").arg(fileName).arg(localFile->errorString()));
                return;
            }
        }else{
            return;
        }
    }
    if(bytesReceived < TotalBytes){
        bytesReceived += tcpClient->bytesAvailable();
        inBlock = tcpClient->readAll();
        localFile->write(inBlock);
        inBlock.resize(0);
    }
    ui->progressBar->setMaximum(TotalBytes);
    ui->progressBar->setValue(bytesReceived);
    qDebug()<tcpClientStatusLabel->setText(tr("已接收 %1MB (%2MB/s) \n共%3MB 已用时:%4秒\n估计剩余时间:%5秒")
                                   .arg(bytesReceived / (1024*1024))//已接收
                                   .arg(speed*1000/(1024*1024),0,'f',2)//速度
                                   .arg(TotalBytes / (1024 * 1024))//总大小
                                   .arg(useTime/1000,0,'f',0)//用时
                                   .arg(TotalBytes/speed/1000 - useTime/1000,0,'f',0));//剩余时间

    if(bytesReceived == TotalBytes)
    {
        tcpClient->close();
        ui->tcpClientStatusLabel->setText(tr("接收文件 %1 完毕").arg(fileName));
	localFile->close();   //接收完文件后,一定要关闭,不然可能出问题
    }
}


void TcpClient::displayError(QAbstractSocket::SocketError socketError) //错误处理
{
    switch(socketError)
    {
        case QAbstractSocket::RemoteHostClosedError : break;
        default : qDebug() << tcpClient->errorString();
    }
}




void TcpClient::on_tcpClientCloseBtn_clicked()//关闭
{
    tcpClient->abort();
    this->close();
}

void TcpClient::on_tcpClientCancleBtn_clicked()//取消
{
   tcpClient->abort();
}


chat.h


#ifndef CHAT_H
#define CHAT_H

#include 
#include 
#include 
#include "tcpclient.h"
#include "tcpserver.h"

namespace Ui {
    class chat;
}

enum MessageType
{
    Message,
    NewParticipant,
    ParticipantLeft,
    FileName,
    Refuse,
    Xchat
};

class chat : public QDialog
{
    Q_OBJECT


public:
    ~chat();
//	chat();
    chat(QString pasvusername, QString pasvuserip);
    QString xpasvuserip;
    QString xpasvusername;
    QUdpSocket *xchat;
    qint32 xport;
    void sendMessage(MessageType type,QString serverAddress="");
	quint16 a;
//	static  qint32 is_opened = 0;
	bool is_opened;

public slots:


protected:
    void hasPendingFile(QString userName,QString serverAddress,  //接收文件
                                QString clientAddress,QString fileName);
    void participantLeft(QString userName,QString localHostName,QString time);
    bool eventFilter(QObject *target, QEvent *event); //事件过滤器

private:
    Ui::chat *ui;
    TcpServer *server;
    QColor color;//颜色
    bool saveFile(const QString& fileName);//保存聊天记录
    QString getMessage();
    QString getIP();
    QString getUserName();
    QString message;
    QString fileName;

private slots:
    void sentFileName(QString);
    void on_sendfile_clicked();
    void processPendingDatagrams();
    void on_send_clicked();
    void on_close_clicked();
    void on_clear_clicked();
    void on_save_clicked();
    void on_textcolor_clicked();
    void on_textUnderline_clicked(bool checked);
    void on_textitalic_clicked(bool checked);
    void on_textbold_clicked(bool checked);
    void on_fontComboBox_currentFontChanged(QFont f);
    void on_fontsizecomboBox_currentIndexChanged(QString );
    void currentFormatChanged(const QTextCharFormat &format);

};

#endif // CHAT_H

#ifndef CHAT_H
#define CHAT_H

#include 
#include 
#include 
#include "tcpclient.h"
#include "tcpserver.h"

namespace Ui {
    class chat;
}

enum MessageType
{
    Message,
    NewParticipant,
    ParticipantLeft,
    FileName,
    Refuse,
    Xchat
};

class chat : public QDialog
{
    Q_OBJECT


public:
    ~chat();
//	chat();
    chat(QString pasvusername, QString pasvuserip);
    QString xpasvuserip;
    QString xpasvusername;
    QUdpSocket *xchat;
    qint32 xport;
    void sendMessage(MessageType type,QString serverAddress="");
	quint16 a;
//	static  qint32 is_opened = 0;
	bool is_opened;

public slots:


protected:
    void hasPendingFile(QString userName,QString serverAddress,  //接收文件
                                QString clientAddress,QString fileName);
    void participantLeft(QString userName,QString localHostName,QString time);
    bool eventFilter(QObject *target, QEvent *event); //事件过滤器

private:
    Ui::chat *ui;
    TcpServer *server;
    QColor color;//颜色
    bool saveFile(const QString& fileName);//保存聊天记录
    QString getMessage();
    QString getIP();
    QString getUserName();
    QString message;
    QString fileName;

private slots:
    void sentFileName(QString);
    void on_sendfile_clicked();
    void processPendingDatagrams();
    void on_send_clicked();
    void on_close_clicked();
    void on_clear_clicked();
    void on_save_clicked();
    void on_textcolor_clicked();
    void on_textUnderline_clicked(bool checked);
    void on_textitalic_clicked(bool checked);
    void on_textbold_clicked(bool checked);
    void on_fontComboBox_currentFontChanged(QFont f);
    void on_fontsizecomboBox_currentIndexChanged(QString );
    void currentFormatChanged(const QTextCharFormat &format);

};

#endif // CHAT_H
chat.c

#include "chat.h"
#include "ui_chat.h"

//chat::chat():ui(new Ui::chat)
//{
//	is_opened = false;
//}


chat::chat(QString pasvusername, QString pasvuserip) : ui(new Ui::chat)
{
    ui->setupUi(this);
    ui->textEdit->setFocusPolicy(Qt::StrongFocus);
    ui->textBrowser->setFocusPolicy(Qt::NoFocus);

    ui->textEdit->setFocus();
    ui->textEdit->installEventFilter(this);

	a = 0;
	is_opened = false;
//	this->is_opened = false;
    xpasvusername = pasvusername;
    xpasvuserip = pasvuserip;

    ui->label->setText(tr("与%1聊天中   对方IP:%2").arg(xpasvusername).arg(pasvuserip));

	//UDP部分
    xchat = new QUdpSocket(this);
    xport = 45456;
 //   xchat->bind(xport, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
	xchat->bind( QHostAddress::QHostAddress(getIP()), xport );
    connect(xchat, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));

	//TCP部分
    server = new TcpServer(this);
    connect(server,SIGNAL(sendFileName(QString)),this,SLOT(sentFileName(QString)));

    connect(ui->textEdit,SIGNAL(currentCharFormatChanged(QTextCharFormat)),this,SLOT(currentFormatChanged(const QTextCharFormat)));
}

chat::~chat()
{
    is_opened = false;
	delete ui;
}

bool chat::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->textEdit)
    {
        if(event->type() == QEvent::KeyPress)//按下键盘某键
        {
             QKeyEvent *k = static_cast(event);
             if(k->key() == Qt::Key_Return)//回车键
             {
                 on_send_clicked();
                 return true;
             }
        }
    }
    return QWidget::eventFilter(target,event);
}

//处理用户离开
void chat::participantLeft(QString userName,QString localHostName,QString time)
{
    ui->textBrowser->setTextColor(Qt::gray);
    ui->textBrowser->setCurrentFont(QFont("Times New Roman",10));
    ui->textBrowser->append(tr("%1 于 %2 离开!").arg(userName).arg(time));
}

QString chat::getUserName()  //获取用户名
{
    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)
            {
                return stringList.at(1);
                break;
            }
        }
    }
    return false;
}

QString chat::getIP()  //获取ip地址
{
    QList list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
       if(address.protocol() == QAbstractSocket::IPv4Protocol) //我们使用IPv4地址
            return address.toString();
    }
       return 0;
}

void chat::hasPendingFile(QString userName,QString serverAddress,  //接收文件
                            QString clientAddress,QString fileName)
{
    QString ipAddress = getIP();
    if(ipAddress == clientAddress)
    {
        int btn = QMessageBox::information(this,tr("接受文件"),
                                 tr("来自%1(%2)的文件:%3,是否接收?")
                                 .arg(userName).arg(serverAddress).arg(fileName),
                                 QMessageBox::Yes,QMessageBox::No);
        if(btn == QMessageBox::Yes)
        {
            QString name = QFileDialog::getSaveFileName(0,tr("保存文件"),fileName);
            if(!name.isEmpty())
            {
                TcpClient *client = new TcpClient(this);
                client->setFileName(name);
                client->setHostAddress(QHostAddress(serverAddress));
                client->show();

            }

        }
        else{
            sendMessage(Refuse,serverAddress);
        }
    }
}

void chat::processPendingDatagrams()   //接收数据UDP
{
    while(xchat->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(xchat->pendingDatagramSize());
        xchat->readDatagram(datagram.data(),datagram.size());
        QDataStream in(&datagram,QIODevice::ReadOnly);
        int messageType;
        in >> messageType;
        QString userName,localHostName,ipAddress,messagestr;
        QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        switch(messageType)
        {
			case Xchat:
			{
//				ui.show();
				break;
			}
            case Message:
                {
					//这2条语句都没有用。why??、
					/*this->hide();
					this->close();*/
                    in >>userName >>localHostName >>ipAddress >>messagestr;
                    ui->textBrowser->setTextColor(Qt::blue);
                    ui->textBrowser->setCurrentFont(QFont("Times New Roman",12));
                    ui->textBrowser->append("[ " +localHostName+" ] "+ time);//与主机名聊天中
                    ui->textBrowser->append(messagestr);
			//		ui->textBrowser->show();
					//this->textBrowser->setTextColor(Qt::blue);
					//this->textBrowser->setCurrentFont(QFont("Times New Roman",12));
					//this->textBrowser->append("[ " +localHostName+" ] "+ time);//与主机名聊天中
					//this->textBrowser->append(messagestr);
			
			//		a ++;
			//		if( is_opened == false )//加了这句,接收端B不显示端口了
					{
						this->show();////解决bug1.收到私聊消息后才显示
				//		ui->textBrowser->show();
					//	this->show();
				//		ui->textBrowser->show();
					//	ui.show();
					//	if( this->show() )
				//		this->hide();
				//		0 == a;
						is_opened = true;
					}
                    break;
                }
        case FileName:
            {
                in >>userName >>localHostName >> ipAddress;
                QString clientAddress,fileName;
                in >> clientAddress >> fileName;
                hasPendingFile(userName,ipAddress,clientAddress,fileName);
                break;
            }
        case Refuse:
            {
                in >> userName >> localHostName;
                QString serverAddress;
                in >> serverAddress;
                QString ipAddress = getIP();

                if(ipAddress == serverAddress)
                {
                    server->refused();
                }
                break;
            }
        case ParticipantLeft:
            {
                in >>userName >>localHostName;
                participantLeft(userName,localHostName,time);
                QMessageBox::information(0,tr("本次对话关闭"),tr("对方结束了对话"),QMessageBox::Ok);
				a = 1;
				ui->textBrowser->clear();
				//is_opened = true;
			//	this->is_opened = false;
				ui->~chat();
                close();
			//	delete ui;
			//	ui = 0;
                break;
            }
        }
    }
}

void chat::sentFileName(QString fileName)
{
    this->fileName = fileName;
    sendMessage(FileName);
}

QString chat::getMessage()  //获得要发送的信息
{
    QString msg = ui->textEdit->toHtml();
    qDebug()<textEdit->clear();
    ui->textEdit->setFocus();
    return msg;
}

//通过私聊套接字发送到对方的私聊专用端口上
void chat::sendMessage(MessageType type , QString serverAddress)  //发送信息
{
    QByteArray data;
    QDataStream out(&data,QIODevice::WriteOnly);
    QString localHostName = QHostInfo::localHostName();
    QString address = getIP();
    out << type << getUserName() << localHostName;


    switch(type)
    {
    case ParticipantLeft:
        {
            break;
        }
    case Message :
        {
            if(ui->textEdit->toPlainText() == "")
            {
                QMessageBox::warning(0,tr("警告"),tr("发送内容不能为空"),QMessageBox::Ok);
                return;
            }
            message = getMessage();
            out << address << message;
            ui->textBrowser->verticalScrollBar()->setValue(ui->textBrowser->verticalScrollBar()->maximum());
            break;
        }
    case FileName:
            {
                QString clientAddress = xpasvuserip;
                out << address << clientAddress << fileName;
                break;
            }
    case Refuse:
            {
                out << serverAddress;
                break;
            }
    }
    xchat->writeDatagram(data,data.length(),QHostAddress::QHostAddress(xpasvuserip), 45456);

}

void chat::currentFormatChanged(const QTextCharFormat &format)
{//当编辑器的字体格式改变时,我们让部件状态也随之改变
    ui->fontComboBox->setCurrentFont(format.font());

    if(format.fontPointSize()<9)  //如果字体大小出错,因为我们最小的字体为9
    {
        ui->fontsizecomboBox->setCurrentIndex(3); //即显示12
    }
    else
    {
        ui->fontsizecomboBox->setCurrentIndex(ui->fontsizecomboBox->findText(QString::number(format.fontPointSize())));

    }

    ui->textbold->setChecked(format.font().bold());
    ui->textitalic->setChecked(format.font().italic());
    ui->textUnderline->setChecked(format.font().underline());
    color = format.foreground().color();
}

void chat::on_fontComboBox_currentFontChanged(QFont f)//字体设置
{
    ui->textEdit->setCurrentFont(f);
    ui->textEdit->setFocus();
}

void chat::on_fontsizecomboBox_currentIndexChanged(QString size)
{
   ui->textEdit->setFontPointSize(size.toDouble());
   ui->textEdit->setFocus();
}

void chat::on_textbold_clicked(bool checked)
{
    if(checked)
        ui->textEdit->setFontWeight(QFont::Bold);
    else
        ui->textEdit->setFontWeight(QFont::Normal);
    ui->textEdit->setFocus();
}

void chat::on_textitalic_clicked(bool checked)
{
    ui->textEdit->setFontItalic(checked);
    ui->textEdit->setFocus();
}

void chat::on_save_clicked()//保存聊天记录
{
    if(ui->textBrowser->document()->isEmpty())
        QMessageBox::warning(0,tr("警告"),tr("聊天记录为空,无法保存!"),QMessageBox::Ok);
    else
    {
       //获得文件名
       QString fileName = QFileDialog::getSaveFileName(this,tr("保存聊天记录"),tr("聊天记录"),tr("文本(*.txt);;All File(*.*)"));
       if(!fileName.isEmpty())
           saveFile(fileName);
    }
}

void chat::on_clear_clicked()//清空聊天记录
{
    ui->textBrowser->clear();
}

bool chat::saveFile(const QString &fileName)//保存文件
{
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly | QFile::Text))

    {
        QMessageBox::warning(this,tr("保存文件"),
        tr("无法保存文件 %1:\n %2").arg(fileName)
        .arg(file.errorString()));
        return false;
    }
    QTextStream out(&file);
    out << ui->textBrowser->toPlainText();

    return true;
}

void chat::on_textUnderline_clicked(bool checked)
{
    ui->textEdit->setFontUnderline(checked);
    ui->textEdit->setFocus();
}

void chat::on_textcolor_clicked()
{
    color = QColorDialog::getColor(color,this);
    if(color.isValid())
    {
        ui->textEdit->setTextColor(color);
        ui->textEdit->setFocus();
    }
}



void chat::on_close_clicked()
{
    sendMessage(ParticipantLeft);
	a = 1;
	ui->textBrowser->clear();
	//is_opened = true;
//	this->is_opened = false;
    close();
	ui->~chat();

	//this->close();
	/*delete ui;
	ui = 0;*/
	
}

void chat::on_send_clicked()
{
    sendMessage(Message);
	QString localHostName = QHostInfo::localHostName();
    QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    ui->textBrowser->setTextColor(Qt::blue);
    ui->textBrowser->setCurrentFont(QFont("Times New Roman",12));
    ui->textBrowser->append("[ " +localHostName+" ] "+ time);
    ui->textBrowser->append(message);
//	is_opened = true;
}

void chat::on_sendfile_clicked()
{
    server->show();
    server->initServer();
}

 

widget.ui--xml



 Widget
 
  
   
    0
    0
    788
    468
   
  
  
   灞€鍩熺綉鑱婂ぉ
  
  
   
    1
   
   
    
     
      6
     
     
      QLayout::SetDefaultConstraint
     
     
      
       
        
         0
         2
        
       
       
        QFrame::Sunken
       
       
        false
       
      
     
     
      
       
        
         
          
           0
           0
          
         
         
          
           1
           25
          
         
        
       
       
        
         
          
           0
           0
          
         
         
          
           0
           25
          
         
         
          true
         
         
          3
         
         
          
           9
          
         
         
          
           10
          
         
         
          
           11
          
         
         
          
           12
          
         
         
          
           13
          
         
         
          
           14
          
         
         
          
           15
          
         
         
          
           16
          
         
         
          
           17
          
         
         
          
           18
          
         
         
          
           19
          
         
         
          
           20
          
         
         
          
           21
          
         
         
          
           22
          
         
        
       
       
        
         
          鍔犵矖
         
         
          false
         
         
          ...
         
         
          
           :/image/textbold.png:/image/textbold.png
         
         
          
           24
           24
          
         
         
          true
         
         
          true
         
        
       
       
        
         
          鍊炬枩
         
         
          false
         
         
          ...
         
         
          
           :/image/textitalic.png:/image/textitalic.png
         
         
          
           24
           24
          
         
         
          true
         
         
          true
         
        
       
       
        
         
          涓嬪垝绾?/string>
         
         
          false
         
         
          ...
         
         
          
           :/image/textunder.png:/image/textunder.png
         
         
          
           24
           24
          
         
         
          true
         
         
          true
         
        
       
       
        
         
          瀛椾綋棰滆壊
         
         
          false
         
         
          ...
         
         
          
           :/image/textcolor.png:/image/textcolor.png
         
         
          
           24
           24
          
         
         
          false
         
         
          true
         
        
       
       
        
         
          浼犻€佹枃浠?/string>
         
         
          false
         
         
          ...
         
         
          
           :/image/fileopen.png:/image/fileopen.png
         
         
          
           24
           24
          
         
         
          false
         
         
          true
         
        
       
       
        
         
          淇濆瓨鑱婂ぉ璁板綍
         
         
          false
         
         
          ...
         
         
          
           :/image/Floppy.png:/image/Floppy.png
         
         
          
           24
           24
          
         
         
          false
         
         
          true
         
        
       
       
        
         
          娓呯┖鑱婂ぉ璁板綍
         
         
          false
         
         
          ...
         
         
          
           :/image/Bin (empty).png:/image/Bin (empty).png
         
         
          
           24
           24
          
         
         
          false
         
         
          true
         
        
       
      
     
     
      
       
        
         0
         1
        
       
       
        
         瀹嬩綋
         12
        
       
       
        

Qt::Horizontal 40 20 100 25 鍏抽棴(&C) 100 25 鍙戦€?&S)
鍦ㄧ嚎鐢ㄦ埛淇℃伅鍒楄〃 QFrame::StyledPanel QAbstractItemView::NoEditTriggers QAbstractItemView::SingleSelection QAbstractItemView::SelectRows false 鐢ㄦ埛鍚?/string> :/image/User.png 涓绘満鍚?/string> IP鍦板潃 0 0 鍦ㄧ嚎鐢ㄦ埛锛?浜?/string> Qt::Horizontal 30 20

tcpserver.ui ---xml



 TcpServer
 
  
   
    0
    0
    350
    180
   
  
  
   鏂囦欢浼犻€?/string>
  
  
   
    
     30
     90
     291
     23
    
   
   
    0
   
  
  
   
    
     10
     10
     331
     71
    
   
   
    
     Agency FB
     12
     75
     true
    
   
   
    璇烽€夋嫨瑕佸彂閫佺殑鏂囦欢锛?/string>
   
   
    Qt::AlignCenter
   
  
  
   
    
     60
     140
     75
     23
    
   
   
    鎵撳紑
   
  
  
   
    
     240
     140
     75
     23
    
   
   
    閫€鍑?/string>
   
  
  
   
    
     150
     140
     75
     23
    
   
   
    鍙戦€?/string>
   
  
 
 
 


tcpclient.ui ---xml



 TcpClient
 
  
   
    0
    0
    350
    180
   
  
  
   鏂囦欢浼犻€?/string>
  
  
   
    
     20
     90
     311
     23
    
   
   
    0
   
  
  
   
    
     140
     140
     75
     23
    
   
   
    鍙栨秷
   
  
  
   
    
     240
     140
     75
     23
    
   
   
    鍏抽棴
   
  
  
   
    
     20
     10
     321
     71
    
   
   
    
     Agency FB
     12
     75
     true
    
   
   
    绛夊緟鎺ユ敹鏂囦欢... ...
   
   
    Qt::AlignCenter
   
  
 
 
 


chat.ui --xml



 chat
 
  
   
    0
    0
    431
    401
   
  
  
   Dialog
  
  
   
    
     10
     40
     411
     351
    
   
   
    
     6
    
    
     QLayout::SetDefaultConstraint
    
    
     
      
       
        0
        2
       
      
      
       QFrame::Sunken
      
      
       false
      
     
    
    
     
      
       
        
         
          0
          0
         
        
        
         
          1
          25
         
        
       
      
      
       
        
         
          0
          0
         
        
        
         
          0
          25
         
        
        
         true
        
        
         3
        
        
         
          9
         
        
        
         
          10
         
        
        
         
          11
         
        
        
         
          12
         
        
        
         
          13
         
        
        
         
          14
         
        
        
         
          15
         
        
        
         
          16
         
        
        
         
          17
         
        
        
         
          18
         
        
        
         
          19
         
        
        
         
          20
         
        
        
         
          21
         
        
        
         
          22
         
        
       
      
      
       
        
         鍔犵矖
        
        
         false
        
        
         ...
        
        
         
          :/image/textbold.png:/image/textbold.png
        
        
         
          24
          24
         
        
        
         true
        
        
         true
        
       
      
      
       
        
         鍊炬枩
        
        
         false
        
        
         ...
        
        
         
          :/image/textitalic.png:/image/textitalic.png
        
        
         
          24
          24
         
        
        
         true
        
        
         true
        
       
      
      
       
        
         涓嬪垝绾?/string>
        
        
         false
        
        
         ...
        
        
         
          :/image/textunder.png:/image/textunder.png
        
        
         
          24
          24
         
        
        
         true
        
        
         true
        
       
      
      
       
        
         瀛椾綋棰滆壊
        
        
         false
        
        
         ...
        
        
         
          :/image/textcolor.png:/image/textcolor.png
        
        
         
          24
          24
         
        
        
         false
        
        
         true
        
       
      
      
       
        
         浼犻€佹枃浠?/string>
        
        
         false
        
        
         ...
        
        
         
          :/image/fileopen.png:/image/fileopen.png
        
        
         
          24
          24
         
        
        
         false
        
        
         true
        
       
      
      
       
        
         淇濆瓨鑱婂ぉ璁板綍
        
        
         false
        
        
         ...
        
        
         
          :/image/Floppy.png:/image/Floppy.png
        
        
         
          24
          24
         
        
        
         false
        
        
         true
        
       
      
      
       
        
         娓呯┖鑱婂ぉ璁板綍
        
        
         false
        
        
         ...
        
        
         
          :/image/Bin (empty).png:/image/Bin (empty).png
        
        
         
          24
          24
         
        
        
         false
        
        
         true
        
       
      
     
    
    
     
      
       
        0
        1
       
      
      
       
        瀹嬩綋
        12
       
      
      
       

Qt::Horizontal 40 20 100 25 鍏抽棴(&C) 100 25 鍙戦€?&S)
10 10 411 21



你可能感兴趣的:(QT)