零、基本概念
什么是信号槽?
信号槽雷同于软件计划模式中的观察者模式,(观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到关照并被自动更新。)被观察者发出的信号(signal),观察者收到自己注册监听signal,就通过槽(slot)关联的槽函数function实现动作操纵。
信号槽的优缺点
(1)类型安全
信号的参数类型、参数个数需要和槽函数的参数类型和参数个数划一。槽函数的个数可以少于信号的参数个数,但缺少的参数必须是信号参数的最后一个或最后几个。
(2)疏松耦合
信号发送者不需要知道发出的信号被哪个对象的槽函数吸收,槽函数也不需要知道哪些信号关联了自己,Qt的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于QObject。
(3)服从
信号槽增强了对象间通讯的灵活性,同时损失了一些性能,通过信号调用的槽函数比直接调用速度慢约10倍(因为需要定位信号吸收者;遍历所有关联;编组/解组转达的参数;多线程时,信号大概需要排队),这种调用速度对性能要求不是非常高的场景是可以忽略的,是满足绝大部分场景。
信号槽的用法和性子
- connect(sender, signal, receiver, slot);
复制代码 sender:发出信号的对象
signal:发送对象发出的信号
receiver:吸收信号的对象
slot:吸收对象在吸收到信号之后所需要调用的函数(槽函数)
系统自带的信号:
- void clicked(bool checked = false)
- void pressed()
- void released()
- void toggled(bool checked )
- signals inherited from Qwidget
- signals inherited from Q0bject
复制代码
- 一个信号可以关联多个槽函数。
- 多个信号可以关联一个槽函数
- 一个信号可以关联另一个信号
- 一个信号关联多个信号
一、Qt焦点机制
- 信号与槽(Signals & Slots)
- 问:Qt的信号槽机制与回调函数有何区别?
- 答:
- 解耦性:信号槽通过元对象系统(Meta-Object System)连接,发送者无需知道吸收者。
- 参数类型安全:编译时检查参数类型(需用Q_DECLARE_METATYPE注册自定义类型)。
- 多对多通讯:一个信号可连接多个槽,反之亦然。
- 线程安全:支持跨线程通讯(自动选择Qt::AutoConnection模式)。
- 元对象系统(Meta-Object System)
- 问:moc(元对象编译器)的作用是什么?
- 答:
- 处理Q_OBJECT宏,天生moc_*.cpp文件,实现信号槽、动态属性、运行时类型信息(RTTI)等功能。
- 支持qobject_cast进行安全的类型转换。
二、内存管理与对象模型
- 父子对象机制
- 问:Qt怎样管理对象的生命周期?
- 答:
- 通过QObject的父子关系:父对象析构时自动销毁所有子对象。
- 示例:QWidget* child = new QWidget(parent);
- 智能指针
- 问:怎样在Qt中利用智能指针?
- 答:
- 利用QSharedPointer、QWeakPointer管理动态对象。
- 留意:QObject及其子类通常依赖父子关系管理,需谨慎混合利用。
三、多线程与并发
- QThread的两种用法
- 问:继承QThread与利用moveToThread有何区别?
- 答:
- 子类化QThread:重写run()方法,适用于需要控制线程实行流程的场景。
- moveToThread:将对象移动到新线程,通过信号槽触发逻辑(更符合事件驱动模型)。
- 线程同步
- 问:Qt中怎样实现线程同步?
- 答:
- 利用QMutex、QReadWriteLock、QSemaphore。
- 跨线程通讯优先利用信号槽(自动排队或阻塞)。
四、事件处理与画图
- 事件循环(Event Loop)
- 问:表明Qt的事件处理流程。
- 答:
- 事件由QApplication进入事件队列。
- QEventLoop逐一分发事件(如鼠标、键盘、定时器事件)。
- 可重写event(QEvent*)或特定事件处理器(如mousePressEvent())。
- 画图机制
- 问:怎样利用QPainter进行自定义画图?
- 答:
- 在paintEvent()中利用QPainter绘制图形。
- 双缓冲技能:通过QPixmap作为临时画布制止闪烁。
五、网络与模型视图编程
- QTcpSocket *socket = new QTcpSocket(this);
- socket->connectToHost("127.0.0.1", 1234);
- connect(socket, &QTcpSocket::readyRead, [=](){
- QByteArray data = socket->readAll();
- // 处理数据
- });
复制代码
- 模型/视图框架
- 问:QAbstractItemModel的作用是什么?
- 答:
- 提供数据接口供视图(如QListView)显示,分离数据与UI。
- 需实现rowCount(), data(), setData()等方法。
六、实际场景问题
- 调试与性能优化
- 问:怎样检测Qt程序的内存泄漏?
- 答:
- 利用工具:Valgrind(Linux)、VLD(Windows)、Qt内置的qDebug()输出对象树。
- 检查未准确父对象化的QObject。
- 跨平台适配
- 问:Qt怎样实现跨平台?
- 答:
- 抽象底层API(如OpenGL、DirectX),提供统一接口。
- 利用Q_OS_WIN、Q_OS_LINUX等宏处理平台差异。
示例代码:信号槽连接
- // 声明
- class Worker : public QObject {
- Q_OBJECT
- public slots:
- void doWork() { /* ... */ }
- };
- // 连接
- QThread thread;
- Worker worker;
- worker.moveToThread(&thread);
- connect(&thread, &QThread::started, &worker, &Worker::doWork);
- thread.start();
复制代码 高频考点总结
- 信号槽的5种连接方式:Qt::AutoConnection(默认)、DirectConnection、QueuedConnection等。
- 事件过滤器:installEventFilter()拦截处理事件。
- 国际化:利用tr()包裹字符串,配合.ts文件翻译。
- 样式表(QSS):雷同CSS,定制控件外观。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |