09计科A23430110陈南博实训二.docx
- 文档编号:5607643
- 上传时间:2022-12-29
- 格式:DOCX
- 页数:22
- 大小:276.93KB
09计科A23430110陈南博实训二.docx
《09计科A23430110陈南博实训二.docx》由会员分享,可在线阅读,更多相关《09计科A23430110陈南博实训二.docx(22页珍藏版)》请在冰豆网上搜索。
09计科A23430110陈南博实训二
上海第二工业大学计算机科学与技术系
学生实训报告
课程名称
嵌入式操作系统课程设计
实训类别
验证型
实训项目名称
创建对话框
班级
09计科A2
姓名
陈南博
学号
20113430110
实训时间
2012年10月24日
实训地点
15号楼507
指导教师
崔莉莉
组号
同组学生信息(请填写在下方)
班级
姓名
学号
一、实训内容、结果与分析
1.完成书本第二部分“创建对话框”中的2.1例题find、2.3例题gotocell、2.4例题sort,其中报告提交find或sort其中一个的代码解释,给出利用Qtdesigner设计gotocell的主要过程和步骤。
三个程序运行结果
2.1Find:
2.3Gotocell:
2.4Sort:
Find的代码及解释:
先看finddialog.h
#ifndefFINDDIALOG_H“防止对这个文件的多重包含”
#defineFINDDIALOG_H书上是这么解释我看了几遍是没看懂什么意思
后来问了老师明白了,是用于自己定义的头文件——防止重复定义
#include
classQCheckBox;简单申明QCheckBox类的存在
classQLabel;简单申明QLabel类的存在
classQLineEdit;简单申明QLineEdit类的存在
classQPushButton;简单申明QPushButton类的存在
classFindDialog:
publicQDialog定义Finddialog作为QDialog的一子类
{
Q_OBJECT对已定义了信号和槽的类,在类定义开始出的Q_OBJECT宏定义是必须的
public:
FindDialog(QWidget*parent=0,constchar*name=0);parent是父类窗口部件,name是这个窗口部件的名称
signals:
信号
voidfindNext(constQString&str,boolcaseSensitive);findNext信号定义
voidfindPrev(constQString&str,boolcaseSensitive);findPrev信号定义
privateslots:
槽
voidfindClicked();定义findclicked槽
voidenableFindButton(constQString&text);定义enableFindButton槽
private:
声明一些私有成员
QLabel*label;声明label成员
QLineEdit*lineEdit;
QCheckBox*caseCheckBox;这几个不再累述
QCheckBox*backwardCheckBox;
QPushButton*findButton;
QPushButton*closeButton;
};
#endif与第一第二行相对应
接下来看finddialog.cpp:
#include
#include
#include
#include
#include
#include"finddialog.h"“”””优先查找相对路径的声明头文件
FindDialog:
:
FindDialog(QWidget*parent,constchar*name)
:
QDialog(parent,name)parent和name传递给基类的构造函数
{
setCaption(tr("Find"));设置窗口标题
label=newQLabel(tr("Find&what:
"),this);新建基于QLabel的label
lineEdit=newQLineEdit(this);新建基于QLineEdit的lineEdit
label->setBuddy(lineEdit);建立关系label与lineedit
caseCheckBox=newQCheckBox(tr("Match&case"),this);新建基于QCheckBox的caseCheckBox
backwardCheckBox=newQCheckBox(tr("Search&backward"),this);新建基于QCheckBox的backwardCheckBox
findButton=newQPushButton(tr("&Find"),this);“&”用于加速键
findButton->setDefault(true);findButton设置为”缺省”
findButton->setEnabled(false);findButton设置为”不可选”
closeButton=newQPushButton(tr("Close"),this);新建基于QPushButton的closeButton
connect(lineEdit,SIGNAL(textChanged(constQString&)),
this,SLOT(enableFindButton(constQString&)));信号lineedit发生调用就调用槽enableFindButton
connect(findButton,SIGNAL(clicked()),
this,SLOT(findClicked()));信号findButton发生clicked()就调用槽findClicked()
connect(closeButton,SIGNAL(clicked()),
this,SLOT(close()));信号closeButton发生clicked()就调用槽close()
QHBoxLayout*topLeftLayout=newQHBoxLayout;新建一个名为topLeftLayout的QHBoxLayou框架
topLeftLayout->addWidget(label);把label放入框架topLeftLayout
topLeftLayout->addWidget(lineEdit);把lineEdit放入框架topLeftLayout
QVBoxLayout*leftLayout=newQVBoxLayout;新建一个名为leftLayout的QHBoxLayou框架
leftLayout->addLayout(topLeftLayout);把topLeftLayout放入框架leftLayout
leftLayout->addWidget(caseCheckBox);把caseCheckBox放入框架leftLayout
leftLayout->addWidget(backwardCheckBox);把backwardCheckBox放入框架leftLayout
QVBoxLayout*rightLayout=newQVBoxLayout;新建一个名为rightLayout的QHBoxLayou框架
rightLayout->addWidget(findButton);把findButton放入框架rightLayout
rightLayout->addWidget(closeButton);把closeButton放入框架rightLayout
rightLayout->addStretch
(1);设置一个弹簧放入框架rightLayout
QHBoxLayout*mainLayout=newQHBoxLayout(this);新建一个名为mainLayout的QHBoxLayou框架
mainLayout->setMargin(11);设置mainLayout边缘
mainLayout->setSpacing(6);设置mainLayout空隙
mainLayout->addLayout(leftLayout);把leftLayout放入框架mainLayout
mainLayout->addLayout(rightLayout);把rightLayout放入框架mainLayout
}
voidFindDialog:
:
findClicked()findclicked槽用于find按键的clicked事件
{
QStringtext=lineEdit->text();linedit的值赋予text()
boolcaseSensitive=caseCheckBox->isOn();打开caseCheckBox
if(backwardCheckBox->isOn())如果backwardCheckBox打开
emitfindPrev(text,caseSensitive);发射findprev信号
else
emitfindNext(text,caseSensitive);否则发射findNext信号
}
voidFindDialog:
:
enableFindButton(constQString&text)enableFindButton槽定义
{
findButton->setEnabled(!
text.isEmpty());lineEdit不为空,find按钮生效
}
Main.cpp:
#include
#include"finddialog.h"头
intmain(intargc,char*argv[])声明
{
QApplicationapp(argc,argv);
FindDialog*dialog=newFindDialog;新建
app.setMainWidget(dialog);
dialog->show();dialog可见
returnapp.exec();运行exe
}
设计gocell主要过程:
QT创建一个dialog
1添加一个文本标签,设置name属性为label,text为&CellLocation:
2添加行编辑器,name-lineedit
3添加间隔期,orientation-horizontal
4添加第一个按钮,name-okbutton,enable-false,default-ture,text-OK
5添加第二个按钮,name-cancelButton,text-Cancel
6窗体本身,name-GoToCellDialog,caption-GotoCell
使用Tools|SetBuddy设置label和edit的伙伴关系
摆放部件
1单击打Celllocation标签下的shift,单击layout|layouthorizontally
2单击间隔器与2个button,使用layout|layouthorizontally
3单击背景取消任何选择,使用layout|layouthorizontally
4单击使用layout|adjustsize
单击tool|taborder设置tab时的空间选中顺序
设置信号与槽
单击edit|connections设计如下
enableOKbutton需要
新建如下
在工程下新建一个main.cpp文件:
#include
#include"gotocelldialog.h"
intmain(intargc,char*argv[])
{
QApplicationapp(argc,argv);
GoToCellDialog*dialog=newGoToCellDialog;
app.setMainWidget(dialog);
dialog->show();
returnapp.exec();
}
生成之后有问题,OK失效行编辑器接受任何文本,而不是接受有效的单元格定位。
结果:
2.理解2.2节“信号与槽”相关内容,查阅资料,写出大约一页A4纸的小论文(字号为五号,行间距为单倍),要求有自己对“信号与槽”的概念理解。
红色是干要部分,黑色是扩充补充,因为原文的逻辑性和语言比较慎密,感觉如果剪切顺序可能并没有原文表达的好,我会扩充一些,我是认真去查看过资料的,并不是随便网上随便拉一篇应付的。
信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为moc(MetaObjectCompiler)的QT工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码。
窗口小部件(widget)都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针。
但是,在QT中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。
信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生coredumps。
所有从QObject或其子类(例如Qwidget)派生的类都能够包含信号和槽。
当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。
这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。
槽用于接收信号,但它们是普通的对象成员函数。
一个槽并不知道是否有任何信号与自己相连接。
而且,对象并不了解具体的通信机制。
可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。
信号
当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。
只有定义过这个信号的类及其派生类能够发射这个信号。
当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。
只有当所有的槽返回以后发射函数(emit)才返回。
如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。
信号的声明是在头文件中进行的,QT的signals关键字指出进入了信号声明区,随后即可声明自己的信号。
例如,下面定义了三个信号:
signals:
voidmySignal();
voidmySignal(intx);
voidmySignalParam(intx,inty);
在上面的定义中,signals是QT的关键字,而非C/C++的。
接下来的一行voidmySignal()定义了信号mySignal,这个信号没有携带参数;接下来的一行voidmySignal(intx)定义了重名信号mySignal,但是它携带一个整形参数,这有点类似于C++中的虚函数。
从形式上讲信号的声明与普通的C++函数是一样的,但是信号却没有函数体定义,另外,信号的返回类型都是void,不要指望能从信号返回什么有用信息。
信号由moc自动产生,它们不应该在.cpp文件中实现。
槽
当一个槽为一个信号来执行的时候,这个返回值就会忽略,但是把槽作为一个函数来调用的时候,返回值对我们的作用和我们调用一个普通的C++函数一样。
槽是普通的C++成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。
当与其关联的信号被发射时,这个槽就会被调用。
槽可以有参数,但槽的参数不能有缺省值。
既然槽是普通的成员函数,因此与其它的函数一样,它们也有存取权限。
槽的存取权限决定了谁能够与其相关联。
同普通的C++成员函数一样,槽函数也分为三种类型,即publicslots、privateslots和protectedslots。
publicslots:
在这个区内声明的槽意味着任何对象都可将信号与之相连接。
这对于组件编程非常有用,你可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
protectedslots:
在这个区内声明的槽意味着当前类及其子类可以将信号与之相连接。
这适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
privateslots:
在这个区内声明的槽意味着只有类自己可以将信号与之相连接。
这适用于联系非常紧密的类。
槽也能够声明为虚函数,这也是非常有用的。
槽的声明也是在头文件中进行的。
信号与槽的关联
最简单的信号与槽的关联:
控件事件——send信号——单目标槽接受——目标控件做出相应
单信号与多槽的关联:
控件事件——send信号——多个目标槽接受——多个目标控件做出相应
信号与信号关联:
控件事件——send信号——目标接受——目标send信号
通过调用QObject对象的connect函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用。
该函数的定义如下:
boolQObject:
:
connect(constQObject*sender,constchar*signal,
constQObject*receiver,constchar*member)[static]
这个函数的作用就是将发射者sender对象中的信号signal与接收者receiver中的member槽函数联系起来。
当指定信号signal时必须使用QT的宏SIGNAL(),当指定槽函数时必须使用宏SLOT()。
如果发射者与接收者属于同一个对象的话,那么在connect调用中接收者参数可以省略。
一个信号甚至能够与另一个信号相关联,
connect(aButton,SIGNAL(clicked()),SIGNAL(aSignal()));
当信号与槽没有必要继续保持关联时,我们可以使用disconnect函数来断开连接。
其定义如下:
boolQObject:
:
disconnect(constQObject*sender,constchar*signal,
constObject*receiver,constchar*member)[static]
这个函数断开发射者中的信号与接收者中的槽函数之间的关联。
有三种情况必须使用disconnect()函数:
断开与某个对象相关联的任何对象。
这似乎有点不可理解,事实上,当我们在某个对象中定义了一个或者多个信号,这些信号与另外若干个对象中的槽相关联,如果我们要切断这些关联的话,就可以利用这个方法,非常之简洁。
disconnect(myObject,0,0,0)或者myObject->disconnect()
断开与某个特定信号的任何关联。
disconnect(myObject,SIGNAL(mySignal()),0,0)或者myObject->disconnect(SIGNAL(mySignal()))
断开两个对象之间的关联。
disconnect(myObject,0,myReceiver,0)或者myObject->disconnect(myReceiver)
在disconnect函数中0可以用作一个通配符,分别表示任何信号、任何接收对象、接收对象中的任何槽函数。
但是发射者sender不能为0,其它三个参数的值可以等于0。
我昨晚实验后有个疑问,每个例题编译完之后都会产生moc_****,那么moc作用又是什么?
元对象编译器moc(metaobjectcompiler)对C++文件中的类声明进行分析并产生用于初始化元对象的C++代码,元对象包含全部信号和槽的名字以及指向这些函数的指针。
moc读C++源文件,如果发现有Q_OBJECT宏声明的类,它就会生成另外一个C++源文件,这个新生成的文件中包含有该类的元对象代码。
例如,假设我们有一个头文件mysignal.h,在这个文件中包含有信号或槽的声明,那么在编译之前moc工具就会根据该文件自动生成一个名为mysignal.moc.h的C++源文件并将其提交给编译器;类似地,对应于mysignal.cpp文件moc工具将自动生成一个名为mysignal.moc.cpp文件提交给编译器。
元对象代码是signal/slot机制所必须的。
用moc产生的C++源文件必须与类实现一起进行编译和连接,或者用#include语句将其包含到类的源文件中。
moc并不扩展#include或者#define宏定义,它只是简单的跳过所遇到的任何预处理指令。
应注意的问题
信号与槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中做到有的放矢,避免产生一些错误。
下面就介绍一下这方面的情况。
1.使用槽与型号会,降低运行效率.信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失,当然这种损失相对来说是比较小的,通过在一台i586-133的机器上测试是10微秒(运行Linux),可见这种机制所提供的简洁性、灵活性还是值得的。
但如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。
2.信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。
因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。
例如,在前面给出的例子中如果在mySlot()槽函数中加上语句emitmySignal()即可形成死循环。
3.如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。
4.宏定义不能用在signal和slot的参数中。
既然moc工具不扩展#define,因此,在signals和slots中携带参数的宏就不能正确地工作,如果不带参数是可以的。
5.构造函数不能用在signals或者slots声明区域内。
的确,将一个构造函数放在signals或者slots区内有点不可理解,无论如何,不能将它们放在privateslots、protectedslots或者publicslots区
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 09 A23430110 陈南博实训二