前面完成了记事本程序的界面制作,这一章将来实现这个程序的编辑菜单上的各项功能。我们使用QTextEdit来作为记事本程序的中心窗体,这里有一个很大的便利就是QTextEdit提供了很多和编辑有关的函数,槽等,在需要的时候只需要直接调用即可,其中,撤销,恢复,复制,粘帖,剪切,全选在QTextEdit均有对应的槽来实现其功能,我们要做的就是把编辑菜单上的动作(QAction)和这些槽连接起来即可,在ReadMe.cxx文件中已经建立了一个用于链接信号与槽的函数
ConnectSingalAndSlot(),现在只需要在这个函数里添加连接
connect(Redo_Action,SIGNAL(triggered()),MainEditWindow,SLOT(redo()));
connect(Undo_Action,SIGNAL(triggered()),MainEditWindow,SLOT(undo()));
connect(Paste_Action,SIGNAL(triggered()),MainEditWindow,SLOT(paste()));
connect(Cut_Action,SIGNAL(triggered()),MainEditWindow,SLOT(cut()));
connect(Copy_Action,SIGNAL(triggered()),MainEditWindow,SLOT(copy()));
connect(SelectAll_Action,SIGNAL(triggered()),MainEditWindow,SLOT(selectAll()));
关于QTextEdit的详细功能,有兴趣的可以查阅QT助手
但QTextEdit并没有提供查询,删除这两个功能,这需要我们自己来实现,对于查询功能,必须对先去的查询对话框(前面完成的FindDialog)再次做一些改动,最初我们只是最做了一个对话框的界面,他只有一个点击“取消”关闭自身的功能,然后为了把这个对话框更好的嵌入记事本程序中,我们修改了这个对话框的关闭事件,使得他被“关闭”的时候只是隐藏而不是真正的关闭,这次,为了实现记事本的查询功能,需要对这个对话框再次改动。
要实现查询对话框的查询功能,需要知道三个信息,查询的内容,是否区分大小写,查询顺序,这三个信息分别来自对话框上的QLineEdit和两个QCheckBox,接下来就是对FindDialog.h文件做些改动,首先添加一个FindWords()的私有槽来获取信息,其次添加一个信号FindWordDetail(const QString& , bool , bool),这个信号用于把查询文本的三个信息通过信号发射出去(即发射给记事本主程序)
在FindDialog.h文件中添加FindWordDetail()信号
//......
signals:
void FindWordDetail(const QString& , bool , bool); //注释1
private slots:
void Find_PushButtonIsEnable(const QString& str); //注释2
void FindWords();
注释1:这个是添加信号,他的三个参数分别对于查询内容,大小写,方向,这些详细信息将会和记事本程序的槽连接,稍后
会实现记事本程序的槽
注释2:还记得这个PushButtonIsEnable()槽吗,在最初的程序中这个槽就已经被实现了,当查询框内容为空的时候,“查
询”按钮不可用,当然在最初的设计中,这个槽被设计为共有的,主要因为最初的时候并不清楚这个操是否需要在
对象外调用,现在可以明确的知道不需要了,所以把这个槽改回私有的。其实这里只是演示下软件设计的存在问题,
很多程序在设计的时候就需要考虑到以后可能的改动,在设计之初就考虑这点可以减少很多以后的麻烦
接下来是实在FindDialog.cxx文件中实现这个槽
void FindDialog::FindWords()
{
bool CaseSensitivity;
bool Direction;
QString Ts;
CaseSensitivity = MatchCase_CheckBox->isChecked();//注释1
Direction = GoBack_CheckBox->isChecked();
Ts = FindString_LineEdit->text();//注释2
emit FindWordDetail(Ts,Direction,CaseSensitivity);//注释3
}
注释1:对于单选按钮QCheckBox,他的成员函数isChecked()返回对象是否被选择,返回结果是布尔值。
注释2:QLineEdit的成员函数text()返回对象的文本内容,返回类型为QString
注释3:这里演示了使用关键字emit用于发射信号,其实"关键字"emit是个宏,QT已经做了处理,当然理解为关键字也不会有
什么问题
最后一步是在FindDialog的构造函数中将“查询”按钮和这个槽链接起来
connect(Find_PushButton,SIGNAL(clicked()),this,SLOT(FindWords()));
这样,当点击“查询”按钮时,就会链接到槽FindWords(),然后这个槽(成员函数)获取对话框的文本内容,大小写,查询方向信息,然后把这3个信息以信号的方式发射出去
在完成了FindDialog的修改后,使得他能提供需要查询的内容的详细信息,然后就是修改记事本的主程序,使得他能接受这些详细信息并最终实现查询功能。在ReadMe.h文件中,添加一个槽
void FindWordInText(const QString& str , bool Direction , bool CaseSensitivity)
在ReadMe.cxx文件中来实现这个槽
void ReadMe::FindWordInText(const QString& str , bool Direction , bool CaseSensitivity)
{
bool FindWord = false;
if(Direction == false and CaseSensitivity == false) //注释1
FindWord = MainEditWindow->find(str);
if(Direction == false and CaseSensitivity == true)
FindWord = MainEditWindow->find(str,QTextDocument::FindCaseSensitively);
if(Direction == true and CaseSensitivity == false)
FindWord = MainEditWindow->find(str,QTextDocument::FindBackward);
if(Direction == true and CaseSensitivity == true)
FindWord = MainEditWindow->find(str,QTextDocument::FindCaseSensitively|QTextDocument::FindBackward);
if(FindWord == false)
QMessageBox::information(this,tr("查询"),tr("无结果"),QMessageBox::Yes); //注释2
}
注释1:QTextEdit提供了一个成员函数find()来实现查询功能,他的原型是find(const QString&,QTextDocument::flags);其中枚
举值QTextDocument::flags用于区分查询方式,如上面函数使用的值FindCasesitively和FindBackward用于表示区别
大小写和查询方向,QTextDocument::flags全部值可以查询QT助手,另外有一点注意的是,前面说过信号与槽的连
接必须保证参数是一致的,否则无法传递对于的数据,这里的一致是区分const的,即信号Signals(const QString&)
和槽Slots(QString&)连接,是无法传递QString的,因为这两个参数一个是const,一个是非const
注释2:这里使用了QMessageBox提供的标准按钮,这个函数的原型是
QMessageBox::information(父对象指针,标题内容,信息内容,按钮);
以这个程序为例,当查询结束是,你希望这个消息框显示内容为“查询结束”,用是界面上有Yes和No两个按钮,那可
以这样写
QMessageBox::information(this,tr("查询"),tr("查询结束"),QMessageBox::Yes|QMessageBox::No);
QMessageBox还提供了warning(),question(),critical()函数,他们有自己特点的图标,同时这些函数均返回点击的按
钮值QMessageBox::StandardButton,这是个枚举值,可以通过返回值来判断用户点击了什么按钮,是Yes,No还是其
他的按钮,要使用这些静态函数,需要在ReadMe.cxx文件中添加头文件#include<QMessageBox>
这样就实现了记事本程序的查询功能
1.当点击编辑菜单的"查询"(QAction)选项后,查询对话框显示(第五章实现)
2.点击对话框的“查询”按钮,查询按钮通过信号连接到FindWords()槽,这个槽获取对话框的详细信息并发射信号,把
这些信息传递给主程序的槽FindWordInText()
3.主程序的槽FindWordInText()使用这些信息,调用QTextEdit的成员函数find()来完成查询功能
在完成查询功能后,还需要实现删除功能,在ReadMe.h中添加一个私有槽DeleteSelectText()然后在ReadMe.cxx中实现这个槽的功能
void ReadMe::DeleteSelectText()
{
MainEditWindow->textCursor().removeSelectedText();//注释1
}
注释1:QTextEdit的成员函数textCursor()返回编辑的文本,以QTextCursor的形式,当然说他是形式其实很不恰当,他是QT
的一个类,QTextCursor主要用于提供操作Access和QTextDocuments的接口,其中QTextDocuments是QT自定义的
一各类,用于把文本转化成QTextDocuments的格式来做进一步的详细处理。这里textCursor()返回前文本已经转化为
QTextDocuments格式,这里调用接口removeSelectedText()就可以实现删除选中文本的动能
然后是查询下一个功能,这个功能的槽为FindNext(),具体实现为
void ReadMe::FindNextWord()
{
if(FindWordsDialog->isHidden()) //注释1
FindWordsDialog->show();
else
{
FindWordsDialog->raise();//注释2
FindWordsDialog->activateWindow();
}
}
注释1:前面已经说明,查询对话框其实没有真正的关闭,只是隐藏,所以这里先用isHidden()判断对话框是否处于隐藏状态
,如果是就把他显示
注释2:对话框有可能处于显示状态,但不是当前窗体,所以调用raise()使对话框处于顶层窗体,activateWindow()使得对话
框处于激活状态
然后是日期/时间功能,这个功能对应的槽是DateAndTime(),具体实现为
void ReadMe::DateAndTime()
{
MainEditWindow->insertPlainText(QDateTime::currentDateTime().toString());//注释1
}
注释1:QTextEdit的成员函数insertPlainText()用于在当前位置插入一个QString,QDateTime的静态函数用于返回一个当前时
间,返回的类型是QDateTime,这个类有成员函数toString()可以很方便的将值转化为QString,使用这个静态函数需要
在ReadMe.cxx中包含头文件#include<QDateTime>
到这里就完成了编辑菜单上剩余的功能,需要做的就是在ConnectSignalAndSlot()函数中添加连接
connect(FindNext_Action,SIGNAL(triggered()),this,SLOT(FindNextWord()));
connect(Delete_Action,SIGNAL(triggered()),this,SLOT(DeleteSelectText()));
connect(DateAndTime_Action,SIGNAL(triggered()),this,SLOT(DateAndTime()));