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

    xiaoxiao2021-03-25  92

    这一章里出要会把前两章制作的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,再编译的时候就不会出现上面的情况了
    转载请注明原文地址: https://ju.6miu.com/read-15083.html

    最新回复(0)