logo资料库

QT最新面试题集.doc

第1页 / 共39页
第2页 / 共39页
第3页 / 共39页
第4页 / 共39页
第5页 / 共39页
第6页 / 共39页
第7页 / 共39页
第8页 / 共39页
资料共39页,剩余部分请下载后查看
★1、QT信号槽机制的优缺点 1)QT信号槽机制的引用精简了程序员的代码量 2)QT的信号可以对
2、描述过程, 如何实现一个自定义按钮, 使其在光标进入,按下,离开三种状态下显示不同的图片. 创
6、 描述QT下udp通信的整个流程 QT下udp通信服务器端和客户端的关系是对等的, 做的处理也
★一、信号与槽
信号和槽机制是Qt的核心机制之一,要掌握Qt编程就需要对信号和槽有所了解。信号和槽是一种高级接口,它
在上面的语句中,signals是Qt的关键字。接下来的一行void yourSignal();定义了
void yourSlot(); void yourSlot(int x); 注意,关键字slo
QObject::connect(scroll, SIGNAL(valueChanged(int))
二、元对象系统
1.元对象系统机制
四、Qt的事件模型
1.事件的概念 
2.事件的创建 
3.事件的交付 
4.事件循环模型 
5.自定义事件 
6.事件与信号的区别 
五、问题与解答 
六、Qt动态布局
七、Qt多线程
1.摘要
2.Qt多线程方法1 继承QThread
2.1写一个继承于QThread的线程
2.2 QThread的几个函数quit、exit、terminate函数
2.3 正确的终止一个线程
2.4 如何正确启动一个线程
3. 继承QThread的一些总结
八、直接继承QObject实现多线
1. 前言
2.继承QObject的多线程实现
3.加锁对性能的影响
4.总结
1.QApplication的主要作用是什么?
2.请写一个调用消息对话框提示报错的程序
3.QT都提供哪些标准对话框以供使用,他们实现什么功能
4、什么是Qt,有什么优点?
★1、QT 信号槽机制的优缺点 1)QT 信号槽机制的引用精简了程序员的代码量 2)QT 的信号可以对应多个槽(但他们的调用顺序随机),也可以多个槽映射一个信号 3)QT 的信号槽的建立和解除绑定十分自由 4)信号槽同真正的回调函数比起来时间的耗损还是很大的,所有在嵌入式实时系统中应当慎用 5)信号槽的参数限定很多,例如不能携带模板类参数,不能出现宏定义等等 2、描述过程, 如何实现一个自定义按钮, 使其在光标进入,按下,离开三种状态下显示不同的 图片. 创建一个类, 让其从 QPushButton 类派生, 重写该类中的事件处理器函数 1>. enterEvent() – 光标进入 2>. leaveEvent() – 光标离开 3>. mousePressEvent() – 鼠标按 下 4>. paintEvent() – 刷新背景图 在每个事件中切换不同的图片, 通过 paintEvent 函数将新的图片 刷新到按钮上手动刷新函数: update() ★3、多线程情况下, Qt 中的信号槽分别在什么线程中执行, 如何控制? 可以通过 connect 函数的第五个参数来控制, 信号槽执行时所在的线程 1>. 直接连接 – 信号槽函数在信号发出者所在线程中执行 2>. 队列连接 – 信号在信号发出者所在线程中执行,槽函数在信号接收者所在线程中执行. 3>. 自动连接 – 多线程时为队列连接方式, 单线程时为直接连接方式 默认情况为自动连接方式. ★4、描述 QT 中的文件流(QTextStream)和数据流(QDataStream)的区别, 他们都 能帮助我们完成一些什么事情. QTextStream : 文本流, 操作轻量级数据(int, double, QString), 数据写入文件中之后以文本的方式呈现。 QDataStream: 数据流, 通过数据流可以操作各种数据类型, 包括类对象, 存储到文件中数据可以还原到内存。 QTextStream, QDataStream 可以操作磁盘文件, 也可以操作内存数据, 通过流对象可以将数据打包 到内存, 进行数据的传输。 5、描述 Qt 下 Tcp 通信的整个流程 服务器端: 1. 创建用于监听的套接字 2. 给套接字设置监听 3. 如果有连接到来, 监听的套接字会发出信号 newConnected 4. 接收连接, 通过 nextPendingConnection()函数, 返回一个 QTcpSocket 类型的套接字对象(用于通 信) 5. 使用用于通信的套接字对象通信 1>. 发送数据: write 客户端: 1. 创建用于通信的套接字 2. 连接服务器: connectToHost 2>. 接收数据: readAll/read
3. 连接成功与服务器通信 1>. 发送数据: write 2>. 接收数据: readAll/read 6、 描述 QT 下 udp 通信的整个流程 QT 下 udp 通信服务器端和客户端的关系是对等的, 做的处理也是一样的. 1. 创建套接字对象 2. 如果需要接收数据, 必须绑定端口 3. 发送数据: writeDatagram 4. 接收数据: readDatagram ★7、描述 QT 下多线程的两种使用方法, 以及注意事项 第一种方法: 1. 创建一个类从 QThread 类派生 2. 在子线程类中重写 run 函数, 将处理操作写入该函数中 3. 在主线程中创建子线程对象, 启动子线程, 调用 start()函数 第二种方法: 1. 将业务处理抽象成一个业务类, 在该类中创建一个业务处理函数 2. 在主线程中创建一 QThread 类对象 3. 在主线程中创建一个业务类对象 4. 将业务类对象移动到子线程中 5. 在主线程中启动子线程 ★8、 通过信号槽的方式, 执行业务类中的业务处理函数多线程使用注意事项: * 1. 业务对象, 构造的时候不能指定父对象 * 2. 子线程中不能处理 ui 窗口(ui 相关的类) * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口 9、描述 Windows 下一个消息从触发到处理的整个路由过程. 应用程序启动, 操作系统为程序创建一个对应的消息队列, 用户对创建进行操作, 产生一系列消息, 操作 系统首先捕捉到这些消息, 将消息投递到对应的消息队列中, 在应用程序中对应一个消息循环 消息循环 每次从消息队列中取出消息, 取出的消息如果是虚拟键消息, 会将其转换成标准消息, 将 转换的消息再 次投递到消息队列, 如果取出的是标准消息, 会将该消息发送给操作系统, 操作系统 会调用对应的窗口 过程函数, 下窗口过程函数中对对用的消息进程处理. 10、在 MFC 窗口中制作一个逃跑按钮(鼠标永远捕捉不到), 该如何实现 创建一个类 MyButton, 让该类从 CButton 类派生 在该子类中处理鼠标移动事件, 鼠标移动到该按钮上, 计算随机位置, 移动按钮 在窗口中拖放一个 CButton 按钮, 给该按钮关联一个 MyButton 类型的变量, 即可 11、 描述 MFC 中的消息映射 MFC 中的消息映射分为三个部分 1. 消息映射声明: DECLARE_MESSAGE_MAP() 2. 执行消息映射的宏
BEGIN_MESSAGE_MAP() // 消息映射入口 ON_WM_PAINT() END_MESSAGE_MAP() 3. 添加消息处理函数的声明和定义 12、描述在 MFC 中如何使用 ODBC 访问 MySQL 数据库? 1. 安装 Mysql 的 odbc 驱动 2. 使用向导添加数据源 3. 创建 MFC 单文档/多文档视图应用程序, 添加数据库支持, 选择数据源, 给数据源中的数据库表绑定 记录集类 4. 通过绑定的记录集对象访问对应的数据库表” 13、QT 如果要进行网络编程首先需要在.pro 中添加如下代码:QT += network 在头文件中包含相关头文件 #include #include 14、QT 的 UdpSocket 接收消息使用原则 第一步:new 一个 UdpSocket 第二步:调用 UdpSocket 的 bind 方法,同时指定端口号 第三步:使用 connect 将接收消息函数和 UdpSocket 对象做关联 第四步:在接受消息槽函数当中调用 readDatagram 接收消息 ★了解 Qt 和 C++的关系 ★掌握 Qt 的信号/槽机制的原理和使用方法 ★了解 Qt 的元对象系统 ★掌握 Qt 的架构 ★理解 Qt 的事件模型,掌握其使用的时机 信号与槽、元对象系统、事件模型是 Qt 机制的核心,如果您想要掌握 Qt 编程,就需要对它 们有比较深入的了解。本章重点介绍了信号与槽的基本概念和用法、元对象系统、Qt 的事件 模型,以及它们在实际使用过程中应注意的一些问题。 Qt 对标准 C++的扩展 标准 C++对象模型为面向对象编程提供了有效的实时支持,但是它的静态特性在一些领域中表现的不够 灵活。事实上,GUI 应用程序往往对实时性和灵活性都有着很高的要求。Qt 通过其改进的对象模型在保 持 C++执行速度的同时提供了所需要的灵活性。 Qt 相对于标准 C++增添的特性主要有以下体现: ◆支持对象间通信:信号与槽机制 ◆支持可查询和可设计的动态对象属性机制 ◆事件和事件过滤器 ◆国际化支持
◆支持多任务的定时器 ◆支持按层检索的对象树 ◆受保护指针 ◆动态类型转换 这些内容是 Qt 核心机制的重要组成部分,在下面的章节中,笔者将有选择的向大家介绍它们。 ★一、信号与槽 信号和槽机制是 Qt 的核心机制之一,要掌握 Qt 编程就需要对信号和槽有所了解。信号和槽是一种高 级接口,它们被应用于对象之间的通信,它们是 Qt 的核心特性,也是 Qt 不同于其它同类工具包的重要地 方之一。在我们所了解的其它 GUI 工具包中,窗口小部件(widget)都有一个回调函数用于响应它们触发 的动作,这个回调函数通常是一个指向某个函数的指针。在 Qt 中用信号和槽取代了上述机制。 1.信号(signal) 当对象的状态发生改变时,信号被某一个对象发射(emit)。只有定义过这个信号的类或者其派生类 能够发射这个信号。当一个信号被发射时,与其相关联的槽将被执行,就象一个正常的函数调用一样。信 号-槽机制独立于任何 GUI 事件循环。只有当所有的槽正确返回以后,发射函数(emit)才返回。 如果 存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地被执行,但是它们 执行的顺序将会是不确定的,并且我们不能指定它们执行的顺序。 信号的声明是在头文件中进行的,并 且 moc 工具会注意不要将信号定义在实现文件中。Qt 用 signals 关键字标识信号声明区,随后即可声 明自己的信号。例如,下面定义了几个信号: signals: void yourSignal(); void yourSignal(int x); 在上面的语句中,signals 是 Qt 的关键字。接下来的一行 void yourSignal();定义了信号 yourSignal,这个信号没有携带参数;接下来的一行 void yourSignal(int x);定义了信号 yourSignal(int x),但是它携带一个整形参数,这种情形类似于重载。 注意,信号和槽函数的声明一般 位于头文件中,同时在类声明的开始位置必须加上 Q_OBJECT 语句,这条语句是不可缺少的,它将告诉 编译器在编译之前必须先应用 moc 工具进行扩展。关键字 signals 指出随后开始信号的声明,这里 signals 用的是复数形式而非单数,siganls 没有 public、private、protected 等属性,这点不同于 slots。 另外,signals、slots 关键字是 QT 自己定义的,不是 C++中的关键字。 还有,信号的声明类似于函数 的声明而非变量的声明,左边要有类型,右边要有括号,如果要向槽中传递参数的话,在括号中指定每个 形式参数的类型,当然,形式参数的个数可以多于一个。 从形式上讲,信号的声明与普通的 C++函数是 一样的,但是信号没有定义函数实现。另外,信号的返回类型都是 void,而 C++函数的返回值可以有丰 富的类型。 注意,signal 代码会由 moc 自动生成,moc 将其转化为标准的 C++语句,C++预处理器 会认为自己处理的是标准 C++源文件。所以大家不要在自己的 C++实现文件实现 signal。 2.槽(slot) 槽是普通的 C++成员函数,可以被正常调用,不同之处是它们可以与信号(signal)相关联。当与 其关联的信号被发射时,这个槽就会被调用。槽可以有参数,但槽的参数不能有缺省值。 槽也和普通成 员函数一样有访问权限。槽的访问权限决定了谁可以和它相连。通常,槽也分为三种类型,即 public slots、
private slots 和 protected slots。 public slots:在这个代码区段内声明的槽意味着任何对象都可将 信号与之相连接。这对于组件编程来说非常有用:你生成了许多对象,它们互相并不知道,把它们的信号 和槽连接起来,这样信息就可以正确地传递,并且就像一个小孩子喜欢玩耍的铁路轨道上的火车模型,把 它打开然后让它跑起来。 protected slots:在这个代码区段内声明的槽意味着当前类及其子类可以将 信号与之相关联。这些槽只是类的实现的一部分,而不是它和外界的接口。 private slots:在这个代 码区段内声明的槽意味着只有类自己可以将信号与之相关联。这就是说这些槽和这个类是非常紧密的,甚 至它的子类都没有获得连接权利这样的信任。 通常,我们使用 public 和 private 声明槽是比较常见的, 建议尽量不要使用 protected 关键字来修饰槽的属性。此外,槽也能够声明为虚函数。 槽的声明也是在 头文件中进行的。例如,下面声明了几个槽: public slots: void yourSlot(); void yourSlot(int x); 注意,关键字 slots 指出随后开始槽的声明,这里 slots 用的也是复数形式。 3.信号与槽的关联 槽和普通的 C++成员函数几乎是一样的-可以是虚函数;可以被重载;可以是共有的、保护的或是 私有的,并且也可以被其它 C++成员函数直接调用;还有,它们的参数可以是任意类型。唯一不同的是: 槽还可以和信号连接在一起,在这种情况下,每当发射这个信号的时候,就会自动调用这个槽。 connect() 语句看起来会是如下的样子: connect(sender, SIGNAL(signal), receiver, SLOT(slot)); 这里的 sender 和 receiver 是指向 QObject 的指针,signal 和 slot 是不带参数的函数名。实际上, SIGNAL()宏和 SLOT()宏会把它们的参数转换成相应的字符串。 到目前为止,在已经看到的实例中,我 们已经把不同的信号和不同的槽连接在了一起。但这里还需要考虑一些其他的可能性。 ⑴一个信号可以连接多个槽 connect(slider, SIGNAL(valueChanged(int)), spinBox, SLOT(setValue(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(updateStatusBarIndicator(int))); 在发射这个信号的时候,会以不确定的顺序一个接一个的调用这些槽。 ⑵多个信号可以连接同一个槽 connect() 无论发射的是哪一个信号,都会调用这个槽。 ⑶一个信号可以与另外一个信号相连接 connect(lineEdit, SIGNAL(textChanged(constQstring&)), this, SIGNAL(updateRecord(const Qstring&))); 当发射第一个信号时,也会发射第二个信号。除此之外,信号与信号之间的连接和信号与槽之间的连 接是难以区分的。 ⑷连接可以被移除 disconnect(lcd, SIGNAL(overflow()), this, SLOT(handleMathError())); 这种情况较少用到,因为当删除对象时,Qt 会自动移除和这个对象相关的所有连接。 ⑸要把信号成功连接到槽(或者连接到另外一个信号),它们的参数必须具有相同的顺序和相同的类 型
connect(ftp ,SIGNAL(rawCommandReply(int, constQString &)), this, SLOT(processReply(int, constQString&))); ⑹如果信号的参数比它所连接的槽的参数多,那么多余的参数将会被简单的忽略掉 connect(ftp, SIGNAL(rawCommandReply(int, constQstring &)), this, SLOT(checkErrorCode(int))); 还有,如果参数类型不匹配,或者如果信号或槽不存在,则当应用程序使用调试模式构建后,Qt 会 在运行时发出警告。与之相类似的是,如果在信号和槽的名字中包含了参数名,Qt 也会发出警告。 信号和槽机制本身是在 QObject 中实现的,并不只局限于图形用户界面编程中。这种机制可以用于 任何 QObject 的子类中。 当指定信号 signal 时必须使用 Qt 的宏 SIGNAL(),当指定槽函数时必须使用宏 SLOT()。如果发射 者与接收者属于同一个对象的话,那么在 connect 调用中接收者参数可以省略。 例如,下面定义了两个对象:标签对象 label 和滚动条对象 scroll,并将 valueChanged()信号与标 签对象的 setNum()相关联,另外信号还携带了一个整形参数,这样标签总是显示滚动条所处位置的值。 QLabel *label=newQLabel; QScrollBar*scroll=newQScrollBar; QObject::connect(scroll, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); 4.信号和槽连接示例 以下是 QObject 子类的示例: class BankAccount : public QObject { Q_OBJECT public: BankAccount () {curBalance=0;} int balance () const {return curBalance;} public slots: void setBalance(int newBalance); signals: void balanceChanged(int newBalance); private: int currentBalance; }; 与多数 C++类的风格类似,BankAccount 类拥有构造函数、balance()“读取”函数和 setBalance()“设置”函数。它还拥有 balanceChanged()信号,帐户余额更改时将发出此信号。发出信 号时,与它相连的槽将被执行。 Set 函数是在公共槽区中声明的,因此它是一个槽。槽既可以作为成员函 数,与其他任何函数一样调用,也可以与信号相连。以下是 setBalance()槽的实现过程: voidBankAccount::setBalance(int newBalance) { if(newBalance != currentBalance) {
currentBalance = newBalance; emit balanceChanged(currentBalance); } } 语句 emit balanceChanged(currentBalance);将发出 balanceChanged()信号,并使用当前新 余额作为其参数。 关键字 emit 类似于“signals”和“slots”,由 Qt 提供,并由 C++预处理器转换成标准 C++语句。 以下 示例说明如何连接两个 BankAccount 对象: BankAccount x, y; connect(&x, SIGNAL(balanceChanged(int)) ,&y, SLOT(setBalance(int))); x.setBalance(2450); 当 x 中的余额设置为 2450 时,系统将发出 balanceChanged()信号。y 中的 setBalance()槽收到 此信号后,将 y 中的余额设置为 2450。一个对象的信号可以与多个不同槽相连,多个信号也可以与特定 对象中的某一个槽相连。参数类型相同的信号和槽可以互相连接。槽的参数个数可以少于信号的参数个数, 这时多余的参数将被忽略。 5.需要注意的问题 信号与槽机制是比较灵活的,但有些局限性我们必须了解,这样在实际的使用过程中才能够做到有的 放矢,避免产生一些错误。下面就介绍一下这方面的情况。 ⑴信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上 还是有所损失,当然这种损失相对来说是比较小的,通过在一台 i586-133 的机器上测试是 10 微秒(运 行 Linux),可见这种机制所提供的简洁性、灵活性还是值得的。但如果我们要追求高效率的话,比如在 实时系统中就要尽可能的少用这种机制。 ⑵信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因 此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。 ⑶如果一个信号与多个槽相关联的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是 随机的,并且我们不能指定该顺序。 ⑷宏定义不能用在 signal 和 slot 的参数中。 ⑸构造函数不能用在 signals 或者 slots 声明区域内。 ⑹函数指针不能作为信号或槽的参数。 ⑺信号与槽不能有缺省参数。 ⑻信号与槽也不能携带模板类参数。 6.小结 从 QObject 或其子类(例如 Qwidget)派生的类都能够使用信号和槽机制。这种机制本身是在 QObject 中实现的,并不只局限于图形用户界面编程中:当对象的状态得到改变时,它可以某种方式将信 号发射(emit)出去,但它并不了解是谁在接收这个信号。槽被用于接收信号,事实上槽是普通的对象成员 函数。槽也并不了解是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。这实际上是“封 装”概念的生动体现,信号与槽机制确保了 Qt 中的对象被当作软件的组件来使用,体现了“软件构件化”的 思想。
二、元对象系统 Qt 的元对象系统是一个基于标准 C++的扩展,能够使 C++更好的适应真正的组件 GUI 编程。它 为 Qt 提供了支持对象间通信的信号与槽机制、实时类型信息和动态属性系统等方面的功能。 元对象系统在 Qt 中主要有以下三部分构成:QObject 类、Q_OBJECT 宏和元对象编译器 moc。 1.元对象系统机制 Qt 的主要成就之一是使用了一种机制对 C++进行了扩展,并且使用这种机制创建了独立的软件组件。 这些组件可以绑定在一起,但任何一个组件对于它所要连接的组件的情况事先都不了解。这种机制称为元 对象系统(meta-object system),它提供了关键的两项技术:信号-槽以及内省(introspection)。内省 功能对于实现信号和槽是必需的,并且允许应用程序的开发人员在运行时获得有关 QObject 子类的“元信 息”(meta-information),包括一个含有对象的类名以及它所支持的信号和槽的列表。这一机制也支持属 性(广泛用于 Qt 设计师中)和文本翻译(用于国际化),并且它也为 QtScirpt 模块奠定了基础。 标准 C++没有对 Qt 的元对象系统所需要的动态元信息提供支持。Qt 通过提供一个独立的 moc 工具解 决了这个问题,moc 解析 Q_OBJECT 类的定义并且通过 C++函数提供可供使用的信息。由于 moc 使用 纯 C++来实现它的所有功能,所以 Qt 的元对象系统可以在任意 C++编译器上工作。 这一机制是这样工作的: ⑴ Q_OBJECT 宏声明了在每一个 QObject 子类中必须实现的一些内省函数,如 metaObject()、 QMetaObject::className()、tr()、qt_metacall(),以及其它一些函数。 ⑵ Qt 的 moc 工具生成了用于由 Q_OBJECT 声明的所有函数和所有信号的实现。 ⑶ 像 connect()和 disconnect()这样的 QObject 的成员函数使用这些内省函数来完成它们的工作。 由于所有这些工作都是由 qmake 和 QObject 类自动处理的,所以很少需要再去考虑这些事情,如果 想进一步了解的话,也可以阅读一下有关 QMetaObject 类的文档和由 moc 生成的 C++源代码文件,可以 从中看出这些实现工作是如何进行的。 2.元对象工具(moc) Qt 的信号和槽机制是采用标准 C++来实现的。该实现使用 C++预处理器和 Qt 所包括的 moc(元对象编译 器)。元对象编译器读取应用程序的头文件,并生成必要的代码,以支持信号和槽机制。 qmake 生成的 Makefiles 将自动调用 moc,所有需要使用 moc 的编译规则都会给自动的包含到 Makefile 文件中。开发人员无需直接使用 moc 编辑、甚至无需查看生成的代码。 除了处理信号和槽以外,moc 还支持 Qt 的翻译机制、属性系统及其扩展的运行时类型信息。比如, Q_PROPERTY()宏定义类的属性信息,而 Q_ENUMS()宏则定义在一个类中的枚举类型列表。Q_FLAGS() 宏定义在一个类中的 flag 枚举类型列表,Q_CLASSINFO()宏则允许你在一个类的 meta 信息中插入 name/value 对。它还使 C++程序进行运行时自检成为可能,并可在所有支持的平台上工作。 元对象编译器 moc(metaobjectcompiler)对 C++文件中的类声明进行分析并产生用于初始化元对象的 C++代码,元对象包含全部信号和槽的名字以及指向这些函数的指针。 moc 读 C++源文件,如果发现有 Q_OBJECT 宏声明的类,它就会生成另外一个 C++源文件,这个新生成 的文件中包含有该类的元对象代码。例如,假设我们有一个头文件 mysignal.h,在这个文件中包含有信号 或槽的声明,那么在编译之前 moc 工具就会根据该文件自动生成一个名为 mysignal.moc.h 的 C++源文件 并将其提交给编译器;类似地,对应于 mysignal.cpp 文件 moc 工具将自动生成一个名为 mysignal.moc.cpp 文件提交给编译器。
分享到:
收藏