一下属于个人见解,有不妥及错误之处,还望不吝指教
大家都晓得,Qt的通信机制就是信号--槽,下面的内容呢,是期望在读者已经了解信号槽的工作方法的基础下的。
怎么样在自己的程序中利用信号和槽的机制,完成需求的同时又能尽量保证代码的精简、条理清晰 有良好可读性和可维护性,是众多接触qt不久的新手伙伴们的一大疑问,通常刚接触时,写出的qt程序是比较紊乱的,代码可读性比较差,下面我就以一个简单的例子,向大家简述下我的见解。
例如我们要完成一个测试LED灯的程序,这个测试程序的功能是通过UI界面的一系列按钮,来发送串口命令给下位机,同时接收返回值,并判断每条命令是成功或者失败,成功,则做出相应反应,例如 计数等用来统计执行的次数等
对于这个需求呢,是与串口相关的,要知道的是,不能直接跨线程操作串口,会出现不可预见的问题,这里我先给大家分享一个模型,应该可以说明一些我的想法:
这个程序中,先定义一个业务类继承自QOBject,类中以槽函数的形式定义所有的串口操作,例如 打开1LED,关闭1LED, 打开2LED, 关闭2LED 等,类完成之后,在.cpp文件起始定义一个自己的全局对象,在头文件中加extern声明,以供其他文件使用。
然后在主线程中定义与业务类对应的信号,并利用全局 业务类对象对信号和槽以Qt::ConnectionType::QueuedConnection的方式建立连接,因为这是跨线程信号槽通信,需要用队列方式,默认是自动选择,我这里就显示指定了,然后继承QThread创建一个工作线程类,在类的run函数中new出业务类对象,然后线程调用this.exec()进入事件循环状态,保持该线程处于始终运行的状态
而后,就可以简单的在对应的按钮的槽中发射需要操作的信号,这样业务类中的槽就会执行操作,完成功能,这样的模式,业务处理和逻辑非常明确,代码的可读性也比较好,可能大家看了这些文字,会觉得云里雾里,没关系,下面用简单的代码来进一步说明问题。
先创建一个C++类作业务类,需要继承自QObject
在业务类中呢,定义串口操作槽函数,在.cpp文件中定义全局对象指针,在头文件中extern声明
然后定义一个工作线程,在线程的run函数中new YW,然后this->exec()事件循环
然后在UI线程代码中,定义工作线程子对象,然后在构造函数中new, 再start();
而后建立槽连接,这里有个需要注意的地方,如果业务类的构造函数中有较耗时的操作,那么在工作线程start()后,对信号和槽函数建立连接的时候会出现连接异常, 原因是g_yw还没有new 成功,还处于NULL状态,所以在connect的时候,报内存异常,这里的解决方法就是,通过qt的exec()中的事件循环机制,来确保g_yw已经成功new出。
通过上面的说明和代码,不晓得大家有没有明白我想分享的见解,如果有问题的话,可以留言。