在這篇文章中,簡單的講述一下在QT中設計一個類比簡訊收發效果的平台。
下面先展示一下會話模組的,如下所示:
介面的標題首先顯示的是“會話中”,接收方後有個下拉式功能表,下拉式功能表初始時顯示的是“無”,下拉式功能表中儲存了電話簿中的所有連絡人,可以進行選擇,當選擇某個連絡人後,在對應的文字框中顯示與所選連絡人相對應的號碼,並且會話視窗的標題也會隨之發生改變,如所示:
選擇接收人後,點擊“發送”按鍵,如果發送的內容為空白,則會出現提示內容“發送內容不可為空”,提醒發送人發送的內容不可為空,如下所示:
當然,如果發送的內容如果不為空白,但是接收人未選擇,則也會出現提示資訊“請選擇收件者”,提醒發送人選擇好接收人資訊,如所示:
當選擇了接收人,且發送的內容不為空白時,則可以進行簡訊的類比收發。接下來我們將使用到測試載入器,用來類比簡訊的接收和發送。測試載入器中使用者姓名為“李立群”,號碼為“8901”,當然也可以設定為其他的資訊。我們在會話視窗的接收人下拉式功能表中選擇“李立群”,在測試載入器的接收人下拉式功能表中選擇之前設定好的使用者資訊,比方說選擇了“翟衛超”,號碼為“4567”,介面如所示:
簡訊類比收發就是類比簡訊的發送和接收,上面已經選擇了兩個人進行通訊,一個是“李立群”,號碼為“8901”,另外一個是“翟衛超”,號碼為“4567”。
對話內容如下所示:
翟衛超:你好啊,最近怎麼樣?
李立群:還好啊,參加了個中興競賽,你呢?
翟衛超:也還行,那你先忙吧!
李立群:好的,下次一起吃飯,拜拜。
翟衛超:拜拜
類比的簡訊收發介面如下所示,在發送內容對話方塊中寫入需要發送的資訊,然後點擊發送,這時,在會話記錄對話方塊中機會記錄該條資訊的發送人姓名,時間和發送的內容,接收時,每次接收到簡訊都會在會話記錄對話方塊中添加所接收的資訊的發送人資訊和接收內容。
如果發送完之後,想發給其他連絡人,只需要改變下拉式功能表中的連絡人,則原先的發送和接收記錄都會清除。
將上述對話內容運行在程式中可得如的:
上面實現了簡訊類比收發的功能,下面我們講述一下黑名單和垃圾簡訊過濾。
首先是黑名單,每次當我們接收到由黑名單發送過來的資訊時,需要將發送資訊儲存到垃圾箱中,為了便於測試,我們在電話簿中設定了一個黑名單資訊,姓名為“丁健”,號碼為“1323”,我們定義了一個XML檔案用來儲存接收到的資訊,在這個檔案中同時儲存著每條資訊的儲存位置。下面用例子來進行說明。
用測試載入器給“翟衛超”發送兩句話“你最近還好嗎?”和“怎麼不說話啊!”,由於發送人是“丁健”,位於黑名單中,所以其發送的資訊不顯示,並且直接放入到垃圾箱中。如所示:
如所示,對於黑名單的發送資訊,接收方並不顯示的,同時,將接收的資訊直接放在垃圾箱中。如所示,在我們定義的儲存資訊內容的XMLMessage.xml檔案中將該條資訊的儲存位置設定為了“垃圾箱”,如所示:
接下來,我們講述一下垃圾簡訊過濾功能。在key.txt文字檔中儲存了屏蔽的關鍵字,我們通過檢查所接收到的資訊中是否含有任何一個屏蔽關鍵字,如果有,則屏蔽該條資訊,在會話記錄視窗中不予顯示內容,且將該條資訊直接放入垃圾箱中。
在電話薄中,“翟衛超”屬於白名單中,在key.txt的文字檔中我們事先設定了一些屏蔽關鍵字,分別為“傻逼”、“我操”、“弄死你”、“TMD”,文字檔如所示:
接下來的說明中,我們將使用“翟衛超”和“李立群”進行簡單的對話,有些資訊含有屏蔽關鍵字,有些資訊不含有屏蔽關鍵字,看對話的具體效果及資訊儲存的具體位置。對話內容如下所示:
李立群:你好啊,小翟!
翟衛超:呵呵,你好啊,你那項目做的咋樣了?
李立群:我操,有點難哦,只能繼續努力了,呵呵。
翟衛超:對啊,只要努力就好!
李立群:對的,拜拜了
上述對話的運行結果如所示:
從上面的對話和資訊儲存圖可以看出,由於“李立群”發送的“我操,有點難哦,只能繼續努力了,呵呵。”中含有屏蔽關鍵字“我操”,所以在“翟衛超”的會話記錄對話方塊中對資訊內容進行了屏蔽,而且也將資訊標記到垃圾箱中。
下面附上相關的程式:
1.dialog.h檔案:
#ifndef DIALOG_H#define DIALOG_H#include <QDialog>#include <ui_dialog.h>#include <qhash.h>#include<qpalette.h>#include<QTextCodec>#include<QtNetwork/QUdpSocket>#include<QtNetwork/qudpsocket.h>#include<QtNetwork/QHostAddress>#include<QtNetwork/qhostaddress.h>#include<QList>namespace Ui {class Dialog;}class Dialog : public QDialog,public Ui_Dialog{ Q_OBJECT public: explicit Dialog(QWidget *parent = 0); void dealmessage(const QString&); bool location(const QString,const QString); ~Dialog();public slots: //顯示接收人的姓名和號碼 void setreciever(const QString&); //寫XML檔案 void writexml(const QString,const QString); //重新命名會話視窗名稱 void renamewintitle(const QString&); //定義發送函數 void send(); //定義接收函數 void recieve();private: QTextCodec *codec; QPalette warning_color; QUdpSocket *udpsocket; //定義變數儲存發送過來資訊的號碼 QString number; //定義變數儲存發送過來資訊的內容 QString content; //用雜湊表儲存電話薄 QHash<QString,QString> qhash_phone; Ui::Dialog *ui; //定義自身資訊 QString my_number;};#endif // DIALOG_H
2.dialog.cpp檔案
#include "dialog.h"#include<ui_dialog.h>#include<QFile>#include<QString>#include<QTextStream>#include<QXmlStreamReader>#include<QXmlStreamWriter>#include<qmessagebox.h>#include<QTime>#include<QIODevice>//建構函式Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog){ ui->setupUi(this); //相容中文字元 codec = QTextCodec::codecForName("GB2312"); QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); //設定自身資訊 my_number="4567"; //設定提醒文本的字型顏色 warning_color.setColor(QPalette::WindowText,Qt::red); ui->label_Warning->setPalette(warning_color); //無發送提醒標誌 ui->label_Warning->setText(tr(" ")); //設定ComboBox的最大顯示個數為5個 ui->comboBox_Phone->setMaxVisibleItems(5); //設定ComboBox的首項為空白 ui->comboBox_Phone->addItem("無","char"); //qhash_phone中添加一個空對空的索引值對 qhash_phone.insert("無"," "); //開啟指定位置的文字檔 QFile phonefile("PhBooks.txt"); //判斷是否開啟成功,唯讀方式開啟 if(phonefile.open(QFile::ReadOnly)) { QString phonebook; //定義兩個字串變數儲存電話薄中的姓名和電話號碼 QString name,phone,inblacklist; //定義一個文字資料流對象in,並用phonefile初始化 QTextStream in(&phonefile); //檢查文字資料流是否到達文字檔的末尾 while(!in.atEnd()) { phonebook=in.readLine(50); //如果沒有,讀取兩行,分別存在姓名和電話號碼變數中 inblacklist=phonebook.left(1); phonebook=phonebook.mid(2); name=phonebook.left(phonebook.indexOf(" ")); phone=phonebook.mid(phonebook.indexOf(" ")+1); //將姓名和電話號碼對應的儲存到一個QHash變數中 qhash_phone.insert(name,phone); //在ComboBox中添加電話薄中的連絡人 ui->comboBox_Phone->addItem(name,"QString"); } //關閉文字檔 phonefile.close(); } else { //如果檔案開啟失敗,在ComboBox中顯示Error ui->comboBox_Phone->addItem("error","char"); } udpsocket=new QUdpSocket; udpsocket->bind(QHostAddress::LocalHost,1573); //ComboBox_Phone選項改變時,LineEdit_Reciever也做相應改變 QObject::connect(ui->comboBox_Phone,SIGNAL(currentIndexChanged(QString)),this,SLOT(setreciever(QString))); //ComboBox_Phone選項改變時,交談視窗的標題隨之發生變化 QObject::connect(ui->comboBox_Phone,SIGNAL(currentIndexChanged(QString)),this,SLOT(renamewintitle(QString))); //ComboBox_Phone選項改變時,清空會話記錄 QObject::connect(ui->comboBox_Phone,SIGNAL(currentIndexChanged(int)),ui->textEdit_Message,SLOT(clear())); //點擊“關閉”按鍵則關閉視窗 QObject::connect(ui->pushButton_Close,SIGNAL(clicked()),this,SLOT(close())); //點擊“發送”時,發送報文資料 QObject::connect(ui->pushButton_Send,SIGNAL(clicked()),this,SLOT(send())); //接收報文資料 QObject::connect(udpsocket,SIGNAL(readyRead()),this,SLOT(recieve()));}//顯示與ComboBox所選姓名相對應的電話號碼在LineEdit_Reciever中void Dialog::setreciever(const QString &name_select){ ui->lineEdit_Reciever->setText(qhash_phone[name_select]);}//判斷資訊儲存位置,false表示收件匣,true表示垃圾箱bool Dialog::location(const QString Number, const QString Content){ //預設情況下為收件匣 bool result=false; //讀電話薄文字檔 QFile phonenumb("PhBooks.txt"); if(phonenumb.open(QFile::ReadOnly)) { QString words; QTextStream in(&phonenumb); //檢查文字資料流是否到達文字檔的末尾 while(!in.atEnd()) { words=in.readLine(50); if(words.contains(Number)) { QString flag=words.left(1); if(flag=="1") { result=true; phonenumb.close(); return result; } } } phonenumb.close(); } else { ui->textEdit_Message->append("PhBooks.txt文字檔開啟失敗!"); } //定義鏈表格儲存體key.txt中的關鍵字 QList<QString> keywordlist; //從key.txt檔案中讀取屏蔽關鍵字,並判斷接收的資訊內容中是否有關鍵字 QFile keyword("key.txt"); if(keyword.open(QFile::ReadOnly)) { QString words; QTextStream in(&keyword); //檢查文字資料流是否到達文字檔的末尾 while(!in.atEnd()) { words=in.readLine(50); keywordlist.append(words); } keyword.close(); } else { ui->textEdit_Message->append("key.txt文字檔開啟失敗!"); } int listlength=keywordlist.count(); for(int i=0;i<listlength;i++) { if(Content.contains(keywordlist.at(i))) { result=true; } } return result;}//寫XML檔案void Dialog::writexml(const QString Number,const QString Content){ //擷取資訊儲存位置 bool loc=location(Number,Content); //定義讀檔案 QFile message_xml("XMLMessage.xml"); //定義寫檔案 QFile message_xml_1("temp.xml"); //開啟檔案 if(!message_xml.open(QIODevice::Text|QIODevice::ReadOnly)) { QMessageBox::about(this,"無法開啟XMLMessage.xml檔案","error"); message_xml.close(); return; } if(!message_xml_1.open(QIODevice::WriteOnly|QIODevice::Text)) { QMessageBox::about(this,"無法開啟temp.xml檔案","error"); message_xml_1.close(); return; } //定義xml檔案的讀寫流 QXmlStreamReader xmlreader(&message_xml); QXmlStreamWriter xmlwriter(&message_xml_1); //是否是XML檔案的第一個元素,即是否是第一條簡訊 bool flag=true; //設定模式 xmlwriter.setAutoFormatting(true); xmlwriter.setCodec(codec); //是否到檔案末尾 while(!xmlreader.atEnd()) { if(xmlreader.isStartDocument()) { xmlwriter.writeStartDocument(); } xmlreader.readNext(); if(xmlreader.isStartElement()) { //如果是XML檔案的第一條資訊,則在之前加入新接收的資訊 if(xmlreader.name().toString()=="Sms"&flag) { xmlwriter.writeStartElement("Sms"); xmlwriter.writeTextElement("Number",Number); xmlwriter.writeTextElement("Name",qhash_phone.key(Number)); xmlwriter.writeTextElement("Content",Content); if(loc) xmlwriter.writeTextElement("Location","垃圾箱"); else xmlwriter.writeTextElement("Location","收件匣"); xmlwriter.writeEndElement(); flag=false; } //讀取元素屬性 QXmlStreamAttributes attr=xmlreader.attributes(); //寫元素名稱 xmlwriter.writeStartElement(xmlreader.name().toString()); //寫元素屬性 if(attr.size()>0) { xmlwriter.writeAttributes(attr); } } if(xmlreader.isCharacters()) { xmlwriter.writeCharacters(xmlreader.text().toString()); } if(xmlreader.isEndElement()) { xmlwriter.writeEndElement(); } } xmlwriter.writeEndDocument(); //關閉讀檔案 message_xml.close(); //關閉寫檔案 message_xml_1.close(); //移除原讀取檔案 message_xml.remove(); //重新命名 QFile::rename("temp.xml","XMLMessage.xml");}//重新命名表單名稱void Dialog::renamewintitle(const QString& title){ QString win_title=""; if(title!="無") win_title="與"+title+"通話中"; else win_title="會話中"; this->setWindowTitle(win_title);}//發送函數實現void Dialog::send(){ //定義儲存發送內容的變數 QString message_send; //定義接收人 QString message_reciever; //擷取發送內容 message_send=ui->textEdit_Sender->toPlainText(); //擷取接收人資訊 message_reciever=ui->lineEdit_Reciever->text(); //判斷髮送內容是否為空白 if(message_send==NULL) { //發送內容為空白時給出提醒 ui->label_Warning->setText(tr("發送內容不可為空!")); return; } else { //清空提醒標誌文本 ui->label_Warning->setText(tr(" ")); //如果接收人為空白 if(message_reciever==NULL) { ui->label_Warning->setText(tr("請選擇收件者!")); return; } else { QString current_time; QDateTime datetime=QDateTime::currentDateTime(); current_time=" "+datetime.time().toString("H:mm:ss"); //在會話記錄中添加發送人 ui->textEdit_Message->append(qhash_phone.key(my_number)+current_time); ui->textEdit_Message->append(" "+message_send); } } //讀取寄件者號碼 QString phonenumber=my_number; //設定發送內容 QString temp="<Sms><Number>"+phonenumber+"</Number><Content>"+message_send+"</Content></Sms>"; //發送資料 udpsocket->writeDatagram(qPrintable(temp),256,QHostAddress::LocalHost,1600); //清空發送內容 ui->textEdit_Sender->clear();}//接收函數實現void Dialog::recieve(){ char buffer[256]; udpsocket->readDatagram(buffer,256,0,0); QString temp(buffer); //處理接收到的字串,分離出號碼和內容 dealmessage(temp); QString current_time; //擷取目前時間 QDateTime datetime=QDateTime::currentDateTime(); current_time=" "+datetime.time().toString("H:mm:ss"); //在會話記錄中添加發送人 ui->textEdit_Message->append(qhash_phone.key(number)+current_time); //判斷該資訊位置 bool blackflag=location(number,content); //如果是黑名單或者資訊中含有屏蔽關鍵字,則屏蔽資訊內容 if(!blackflag) { ui->textEdit_Message->append(" "+content); } else { ui->textEdit_Message->append(" "); } //向XML檔案中寫入接收的資訊 writexml(number,content);}//報文資料處理函數void Dialog::dealmessage(const QString &numb_cont){ //找到發送號碼的起始位置 int numb_start=numb_cont.indexOf("<Number>")+8; QString temp=numb_cont.mid(numb_start); //找到發送號碼的結束位置 int numb_end=temp.indexOf("</Number>"); //得到發送號碼 number=temp.left(numb_end); //找到發送內容的起始位置 int cont_start=numb_cont.indexOf("<Content>")+9; temp=numb_cont.mid(cont_start); //找到發送內容的結束位置 int cont_end=temp.indexOf("</Content>"); //得到發送內容 content=temp.left(cont_end);}//解構函式Dialog::~Dialog(){ delete ui;}
3.main.cpp檔案
#include <QtGui/QApplication>#include "dialog.h"#include <QTextStream>int main(int argc, char *argv[]){ QApplication a(argc, argv); Dialog w; w.show(); return a.exec();}
說明:測試專案程式和上述程式基本相同,只需修改相應的連接埠號碼即可。