📄 mywindow.cpp
字号:
#include <QtGui>#include <QtNetwork>#include <stdlib.h>#include "mywindow.h"//构造函数,初始化登录窗口MyWindow::MyWindow(){ //创建登录界面的各个部件 logOnDialog = new QDialog(this); QLabel *logOnLabel = new QLabel(tr("Please input your nickname"),logOnDialog); logOnName = new QLineEdit(QHostInfo::localHostName(),logOnDialog); QPushButton *logOnButton = new QPushButton(tr("&Log on"),logOnDialog); connect(logOnButton, SIGNAL(clicked()), this, SLOT(initialize())); QPushButton *exitButton = new QPushButton(tr("&Exit"),logOnDialog); connect(exitButton, SIGNAL(clicked()), this, SLOT(close())); //登录界面的布局 QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addWidget(logOnLabel); topLayout->addWidget(logOnName); QHBoxLayout *bottomLayout = new QHBoxLayout; bottomLayout->addStretch(1); bottomLayout->addWidget(logOnButton); bottomLayout->addWidget(exitButton); QGridLayout *logOnLayout = new QGridLayout; logOnLayout->addLayout(topLayout,0,0); logOnLayout->addLayout(bottomLayout,1,0); logOnDialog->setLayout(logOnLayout); logOnDialog->show();}//处理关闭事件void MyWindow::closeEvent(QCloseEvent *event){ //广播用户注销信息 writeData(2); //接受信号,执行退出 event->accept();}//关于本程序void MyWindow::about(){ QMessageBox::information(this, tr("About"),tr("About application"));}//激活发送按钮void MyWindow::enabledSendButton(){ sendButton->setEnabled(true);}//处理进来的UDP数据包void MyWindow::receiveMessage(){ /*解码信息 0+昵称+主机名 为新用户广播注册 1+昵称+主机名 为已经登录用户回应新用户注册 2+昵称+主机名 为用户注销,退出聊天室 3+昵称+正文 为正常的数据包信息 4+图片名+图片数据 为图片数据 */ while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); //开始解码 int receiveFlag; //保存解码数据包后的标志 QString receiveHostName; //保存解码数据包后的主机名 QString receiveUserName; //保存解码后的数据包的用户昵称 QDataStream in(&datagram, QIODevice::ReadOnly); //解析标志 in >> receiveFlag; //是图像文件UDP数据包,保存图片到文件夹 temp-image/下 if(receiveFlag == 4) { QString tempFileName; in >> tempFileName; tempFileName = QString(("temp-image/") + tempFileName); QImage image; in >> image; QImageWriter imageWrite(tempFileName); imageWrite.setFormat(QFileInfo(tempFileName).suffix().toAscii()); imageWrite.write(image); continue; } //解析昵称 in >> receiveUserName; //正常的数据交流 if(receiveFlag == 3) { in >> message; recordTextEdit->append( "\n[ " + QDateTime::currentDateTime().toString(tr("yyyy-MM-dd hh:mm:ss")) + " ] " + receiveUserName + tr(" say:\n\t") ); recordTextEdit->append(message); QSound::play("data/msg.wav"); continue; } //解析主机名 in >> receiveHostName; //如果是自己发的消息,不作处理,返回 if( ( receiveHostName == QHostInfo::localHostName()) && (receiveUserName == userName) ) { continue; } //新用户注册数据包,添加新登录的用户信息到自己的用户列表 if(receiveFlag == 0) { QSound::play("data/Global.wav"); //显示新用户登录事件 recordTextEdit->append( "\n[ " + QDateTime::currentDateTime().toString(tr("yyyy-MM-dd hh:mm:ss")) + tr(" ] System information \n\t") + receiveUserName + comeList.at(rand() % comeList.size())); //回送数据包 writeData(1); //如果用户已经存在,那么不添加 int count = 0; for(count = 0; count < hostStringList->size(); count ++) { if( (receiveHostName == hostStringList->at(count)) && (receiveUserName == userListWidget->item(count)->text()) ) { break; } } if(count >= hostStringList->size()) { //hostStringList 保存用户的主机名,userListWidgetItem保存用户昵称,两者一一对应 hostStringList->append(receiveHostName); userListWidgetItem = new QListWidgetItem(QIcon(":/data/QQ.png"),receiveUserName,userListWidget); } continue; } //相应新用户注册的回送数据包。如果用户已经存在,忽略之,否则添加到自己的聊天室用户表 if(receiveFlag == 1) { //如果用户已经存在,忽略之 int count = 0; for(count = 0; count < hostStringList->size(); count ++) { if( (receiveHostName == hostStringList->at(count)) && (receiveUserName == userListWidget->item(count)->text()) ) { break; } } if(count >= hostStringList->size()) { //添加 hostStringList->append(receiveHostName); userListWidgetItem = new QListWidgetItem(QIcon(":/data/QQ.png"),receiveUserName,userListWidget); } continue; } //用户注销事件,如果用户存在,则删除之 if(receiveFlag == 2) { for( int count = 0; count < hostStringList->size(); count ++) { if( (receiveHostName == hostStringList->at(count)) && (receiveUserName == userListWidget->item(count)->text())) { hostStringList->removeAt(count); userListWidget->takeItem(count); break; } } recordTextEdit->append( "\n[ " + QDateTime::currentDateTime().toString(tr("yyyy-MM-dd hh:mm:ss")) + tr(" ] System information \n\t") + receiveUserName + leaveList.at(rand() % leaveList.size())); continue; } } }//发送消息void MyWindow::sendMessage(){ message = inputTextEdit->toHtml(); writeData(3); //清除发送框 inputTextEdit->clear(); }//写数据到网络void MyWindow::writeData(int flag){ /*编码工作 0+昵称+主机名 为新用户广播注册 1+昵称+主机名 为已经登录用户回应新用户注册 2+昵称+主机名 为用户注销,退出聊天室 3+昵称+正文 为正常的数据包信息 4+图片名+图片数据 为图片数据*/ QByteArray datagram; QDataStream out(&datagram,QIODevice::WriteOnly); out << flag; out << userName; if(flag == 3) { out << message; } else { out << QHostInfo::localHostName(); } udpSocket->writeDatagram(datagram.data(), qint64(datagram.size()), QHostAddress::Broadcast, defaultPort);}//设置字体颜色void MyWindow::setFontColor(){ QColor col = QColorDialog::getColor(inputTextEdit->textColor(), this); if (!col.isValid()) { return; } inputTextEdit->setTextColor(col); QPixmap pix(16, 16); pix.fill(col); colorButton->setIcon(pix);}//槽函数,打开图片文件void MyWindow::openImage(){ //实现图像同步的策略为,先复制图像到自己和别人机器的 temp-image/ 下,然后在数据包中加入HTML的显示本地图像代码 QString image = QFileDialog::getOpenFileName(this, tr("Open Image File..."), "temp-image/", tr("Image-Files (*.png *.gif *.bmp *.jpeg *.jpg)")); QFile::copy(image, QString("temp-image/") + QFileInfo(image).fileName()); if (image.isEmpty()) { return; } inputTextEdit->append("<img src='temp-image/" + QFileInfo(image).fileName() + "' />"); //广播图片 QByteArray datagram; QDataStream out(&datagram,QIODevice::WriteOnly); out << 4; out << QFileInfo(image).fileName(); QImageReader imageReader(image); imageReader.setFormat(QFileInfo(image).suffix().toAscii()); out << imageReader.read(); udpSocket->writeDatagram(datagram.data(), qint64(datagram.size()), QHostAddress::Broadcast, defaultPort);}//槽函数,设置字体大小void MyWindow::setFontSize(const QString &size){ inputTextEdit->setFontPointSize(size.toFloat());}//槽函数,设置输入字体为粗体void MyWindow::setBoldFont(bool flag){ if(flag == true) { inputTextEdit->setFontWeight(QFont::Bold); } else inputTextEdit->setFontWeight(QFont::Normal);}//初始化聊天室界面和程序基本信息void MyWindow::initialize(){ userName = logOnName->text(); logOnDialog->close(); resize(800,600); //setMinimumSize(800,600); setMaximumSize(800,600); setWindowTitle(tr("localqq")); messageWindow = new QWidget(this); messageWindow->resize(800,600); recordTextEdit = new QTextEdit(messageWindow); recordTextEdit->setReadOnly(true); recordTextEdit->setMinimumSize(600,300); inputTextEdit = new QTextEdit(messageWindow); //inputTextEdit->setMinimumSize(490,100); inputTextEdit->setMaximumSize(600,180); editToolBar = new QToolBar(messageWindow); //编辑工具栏上的字体 fontComboBox = new QComboBox(editToolBar); editToolBar->addWidget(fontComboBox); fontComboBox->setEditable(true); QFontDatabase fontDB; fontComboBox->addItems(fontDB.families()); connect(fontComboBox, SIGNAL(activated(const QString &)), inputTextEdit, SLOT(setFontFamily(const QString &))); fontComboBox->setCurrentIndex(fontComboBox->findText(QApplication::font().family())); //编辑工具栏的字体大小 sizeComboBox = new QComboBox(editToolBar); editToolBar->addWidget(sizeComboBox); sizeComboBox->setEditable(true); foreach(int size, fontDB.standardSizes()) sizeComboBox->addItem(QString::number(size)); connect(sizeComboBox, SIGNAL(activated(const QString &)), this, SLOT(setFontSize(const QString &))); sizeComboBox->setCurrentIndex(sizeComboBox->findText(QString::number(QApplication::font().pointSize()))); //粗体 boldButton = new QToolButton(editToolBar); editToolBar->addWidget(boldButton); boldButton->setCheckable(true); boldButton->setIcon(QIcon(":/data/textbold.png")); connect(boldButton, SIGNAL(toggled(bool)), this, SLOT(setBoldFont(bool))); //斜体 italicButton = new QToolButton(editToolBar); editToolBar->addWidget(italicButton); italicButton->setCheckable(true); italicButton->setIcon(QIcon(":/data/textitalic.png")); connect(italicButton, SIGNAL(toggled(bool)), inputTextEdit, SLOT(setFontItalic(bool))); //下划线 underlineButton = new QToolButton(editToolBar); editToolBar->addWidget(underlineButton); underlineButton->setCheckable(true); underlineButton->setIcon(QIcon(":/data/textunder.png")); connect(underlineButton, SIGNAL(toggled(bool)), inputTextEdit, SLOT(setFontUnderline(bool))); //颜色 colorButton = new QToolButton(editToolBar); editToolBar->addWidget(colorButton); colorButton->setIcon(QIcon(":/data/textcolor.png")); connect(colorButton, SIGNAL(clicked()), this, SLOT(setFontColor())); //打开图片 imageButton = new QToolButton(editToolBar); editToolBar->addWidget(imageButton); imageButton->setIcon(QIcon(":/data/openimage.png")); connect(imageButton, SIGNAL(clicked()), this, SLOT(openImage())); //发送按钮 sendButton = new QPushButton(tr("&Send"), messageWindow); sendButton->setEnabled(false); connect(inputTextEdit, SIGNAL(textChanged()), this, SLOT(enabledSendButton())); connect(sendButton, SIGNAL(clicked()), this, SLOT(sendMessage())); //关于按钮 aboutButton = new QPushButton(tr("&About"),messageWindow); connect(aboutButton, SIGNAL(clicked()), this, SLOT(about())); //用户昵称表 userListWidget = new QListWidget(messageWindow); //userListWidget->setMinimumSize(120,420); userListWidget->setMaximumSize(180,600); //退出按钮 quitButton = new QPushButton(tr("&Quit"),messageWindow); connect(quitButton,SIGNAL(clicked()), this, SLOT(close())); //布局 QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addWidget(aboutButton); buttonLayout->addStretch(3); buttonLayout->addWidget(sendButton); buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); QVBoxLayout *leftLayout = new QVBoxLayout; leftLayout->addWidget(recordTextEdit); leftLayout->addWidget(editToolBar); leftLayout->addWidget(inputTextEdit); QGridLayout *mainLayout = new QGridLayout; mainLayout->addLayout(leftLayout,0,0); mainLayout->addWidget(userListWidget,0,1); mainLayout->addLayout(buttonLayout,1,0,1,2); mainLayout->setSizeConstraint(QLayout::SetFixedSize); messageWindow->setLayout(mainLayout); messageWindow->show(); //初始化默认端口和主机列表 defaultPort = quint16(22222); hostStringList = new QStringList(); //用户登录和离开的致词表 comeList << tr("come1") << tr("come2") << tr("come3") << tr("come4") << tr("come5") << tr("come6"); leaveList << tr("leave1") << tr("leave2") << tr("leave3") << tr("leave4") << tr("leave5") << tr("leave6"); //监听UDP数据包,如果有数据包抵达调用receiveessag槽进行处理 udpSocket = new QUdpSocket(this); udpSocket->bind(defaultPort); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(receiveMessage())); //发送新用户登录信息数据包 writeData(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -