Essential Qt 第五章 记事本(二)简单事件处理

          这一章里出要会把前两章制作的2个窗体合并为一个程序,这里需要我们手动修改一个关闭事件,在Qt编程中,事件是一个很重要的部分,后面将会一单独的章节来详细讲述,但应为这个程序就会用到,所以在这一章简单的介绍下。
           事件(event)是由窗口系统或者Qt自身产生,用以响应所发生的各类事情。就如第一章里的使用到的窗部件QPushButton,当鼠标(左键或右键)点击就会触发这个窗体的mousePressEvent()事件,双击就会触发mouseDoubleClickEvent(),当你关闭一个窗体时就会触发他的closeEvent()事件,这些事件可以根据需要进行修改,比如这章的例子,我们需要修改窗体的关闭时间,使得用户点击关闭的时候,窗体隐藏而不是关闭。
          另外需要说明的是,在Qt的类中,大多数事件属于类的保护函数,

          首先来看上一章制作的ReadMe程序,在这个程序的“编辑”菜单中有“查询”这个选项,我们希望点击查询的时候能够跳出第三章完成的对话框FindDialog.一个比较简单的方法就是在ReadMe程序中添加一个FindDialog对象,然后通过信号与槽链接,即点击“查询”后,显示FindDialog对象,然后点击对话框的取消来删除该对象。但这里遇到一个问题,FindDialog对象显示后用户如果再次点击"查询“对话框,就会创建第二个FindDialog,这显然不符合常理,对于这类情况,可以通过判断该对象是否存在来,但显得有点麻烦,另外这样需要多次生产/删除一个FindDialog对象,频繁的向系统申请内存并不是一个好习惯。
          这里有一个更”取巧“的办法,关键就在于FindDialog类上,当点击对话框上的”取消“来关闭这个对象,我们修改下这个类的关闭事件,使得他不是关闭,而仅仅是隐藏,那上面的问题就可以得到解决,当点击”查询"就显示FindDialog,用户点击"取消"的时候对话框消失,但他其实只是隐藏了,下次用户再次点击查询的时候对话框就会再次显示(show()函数),另外对已经显示的窗体调用show()函数不会有任何影响,这也避免了用户多次点击查询而跳出多个对话框的问题

            首先是对FindDialog.h文件最一些修改
#include<QDialog>
#include<QLineEdit>
#include<QCheckBox>
#include<QPushButton>
#include<QLabel>
#include<QCloseEvent>  //注释1
class FindDialog:public QDialog
{
  Q_OBJECT
  private:
    QLabel* Title_Label;
    QLineEdit* FindString_LineEdit;
    QPushButton* Find_PushButton;
    QPushButton* Close_PushButton;
    QCheckBox* MatchCase_CheckBox;
    QCheckBox* GoBack_CheckBox;
  public:
    FindDialog(QWidget* parents = 0);
  protected:
    void closeEvent(QCloseEvent* event);  //注释2
  public slots:
    void Find_PushButtonIsEnable(const QString& str);
};


注释1 :这里新包含了一个头文件,用于事件函数的参数,虽然这个参数没什么用
注释2 :关闭事件函数,注意这是一个protected函数,这个函数原先作用是关闭自身,而这里我们需要他不是
              关闭自身窗体,而是隐藏窗体
            在FindDialog.cxx文件改动就是要实现这个保护函数(事件),代码很简单
void FindDialog::closeEvent(QCloseEvent* event)
{
  hide();
}


           这个函数的功能从原先的关闭窗体变成了隐藏窗体
           然后要做的就是把这个改好的FindDialog对话框安装到ReadMe上,在ReadMe.h头文件中包含这个类,另外由于需要信号与槽的链接,出于模块化的设计目的,我们在ReadMe.h头文件中再添加一个私有函数,用于信号与槽的链接,这样ReadMe.h文件将添加下面的代码
#include"FindDialog.h"
//.
//.
void ConnectSignalAndSlot();


          在ReadMe.cxx中首先需要需要实现这个新添加的私有函数
void ReadMe::ConnectSignalAndSlot()
{
  connect(Find_Action,SIGNAL(triggered()),FindWordsDialog,SLOT(show()));
}


           这里将动作"查询"和对话框的show()连接起来,QAction被点击后会发出triggered()信号,最后需要改动的是构造函数,这里我贴出改动后的构造函数的完成代码
ReadMe::ReadMe(QWidget* parent):QMainWindow(parent)
{
  CreateAction();
  CreateMenu();
  CreateMenuBar();
  MainEditWindow = new QTextEdit;
  setCentralWidget(MainEditWindow);
  FindWordsDialog = new FindDialog(this);  //注释1
  setWindowTitle(tr("记事本"));
  ConnectSignalAndSlot();  //注释2
}


注释1 : FindDialog的构造函数的参数是QWidget* parent = 0;具有默认参数,如果他是顶层窗体,就没有父窗
               体,参数为0,如果就就使用父窗体的指针作为参数,这里FindDialog的父窗体是this
注释2 :注意这个用于链接信号和槽的函数的调用顺序,必需等所有对象都创建后才能进行连接,连接到一个未
              创建的对象的话,在程序运行是会出现段错误

           最后把修改后的文件进行重新编译,如果你是在使用GCC编译器的话会出现类似这样的错误信息
           FindDialog.o:在函数‘FindDialog::FindDialog(QWidget*)’中:
           FindDialog.cxx:(.text+0x19):对‘vtable for FindDialog’未定义的引用
           FindDialog.cxx:(.text+0x20):对‘FindDialog::staticMetaObject’未定义的引用
           collect2: error: ld returned 1 exit status
           如果你使用的是VS系列编译器也会出现类似的情况

         之所以会出现这个问题是因为在上一章的ReadMe程序中只是单纯的界面制作,而没用涉及他的功能,更确切的说是没有用到信号与槽,而在这章的例子添加了信号与槽,在私有函数ConnectSignalAndSlot()中,而一旦莫个类需要使用信号与槽,就必须在头文件中添加Q_OBJECT这个宏,添加这个宏后,再使用make -project重新生产MakeFile,再编译的时候就不会出现上面的情况了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值