从C++ GUI Qt4编程示例看Qt5的信号槽演变
本帖最后由 dbgcode 于 2022-2-27 14:15 编辑从C++ GUI Qt4编程示例看Qt5的信号槽演变
本示例是在Qt5.6.3中演示
该书是Qt入门经典书籍,可谓信息量详多,不适合零基础人士。
一、第一章三个小示例引入常用概念。
二、关于信号槽函数重载。
一、示例1带你熟悉Qt编程基本框架和编译步骤
#include <QApplication> //要在项目PRO文件中添加 QT += widgets,否则编译失败。
#include <QLabel> //1、是窗口程序必须包含的类,2、是输出helloQt的标签类
int main(int argc, char *argv[]) //所有基于C++的程序必有的入口函数
{
QApplication app (argc,argv); //初始化窗口必须的实例,必须在Q_OBJECT宏前定义。
/* QLabel *lebel=new QLabel("Hello Qt"); //对象生成在堆上,没有delete,有内存泄漏.
label->show
*/
QLabel label("helloQt"); //修改为创建在栈上,由程序自动管理。
//QLabel label("<h2><i>hello</i>""<font color=red>Qt</font></h2>");
label.show(); //显示创建的窗口在代码结束
return app.exec(); //使程序代码一直执行,进入事件循环,直到用户点击退出。
}
示例2引入了信号槽机制
#include <QApplication>
#include<QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
QPushButton button("quit");
button.show();
//QObject::connect(&button,SIGNAL(clicked(bool)),&app,SLOT(quit())); //Qt4写法
QObject::connect(&button,&QPushButton::clicked,&app,&QApplication::quit); //Qt5写法
return app.exec();
}
示例3引入布局的概念,让你从繁复的设置部件位置和大小中脱离出来。
#include <QApplication>
#include <QHBoxLayout>
#include <QSlider>
#include <QSpinBox>
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
QWidget window;
window.setWindowTitle("Enter You Age");
QSpinBox spinBox;
QSlider slider(Qt::Horizontal);
spinBox.setRange(0,130);
slider.setRange(0,130);
/*//带SIGNAL和SLOT的是Qt4通用写法
QObject::connect(&spinBox,SIGNAL(valueChanged(int)),&slider,SLOT(setValue(int)));
QObject::connect(&slider,SIGNAL(valueChanged(int)),&spinBox,SLOT(setValue(int)));
*/
void (QSpinBox::*sb)(int)=&QSpinBox::valueChanged;//valueChanged有重载,指针要精确匹配函数才能作为信号
QObject::connect(&spinBox,sb,&slider,&QSlider::setValue); //Qt5.6写法
QObject::connect(&slider,&QSlider::valueChanged,&spinBox,&QSpinBox::setValue);
spinBox.setValue(35);
QHBoxLayout layout;
layout.addWidget(&spinBox);
layout.addWidget(&slider);
window.setLayout(&layout);
window.show();
return app.exec();
}
Qt5和Qt4比较多了两个connnect()函数重载,以及信号槽的类型检查。Qt4在运行时才检查,Qt5可以在编译时检查。
Qt4常用原型和新增函数原型如下:
QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)
QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection)
QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
可见Qt4和5的发送者和接收者没有变化或者只是省略而已。不同的只是信号槽的类型变化,以前是字符指针型(需要用相应SIGNAL()或SOLT()宏转换),现在变为函数指针型(直接在函数前加&取地址符就好,书写简单了)。
二、关于信号槽的函数重载
在信号槽没有函数重载时Qt5比Qt4书写简单,且有类型检查,通过上面示例也可以看出来。
有重载时,因为信号槽是函数指针,而函数指针必须要指定的具体的函数,也就是说重载的每个函数都要指定一个函数指针,才能在connect()里使用。
但你没有明确初始化一个重载的信号槽函数时,直接使用信号槽函数的名称,编译器会因为不知道具体调用哪个重载的函数而报错。
上面的示例3使用了C语言的方式处理的信号槽。而在C++中建议是下面的处理方式:
QObject::connect(&spinBox,static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),&slider,&QSlider::setValue);
上面是在Qt5.7之前的写法,在Qt5.7及以后的写法是这样:
QObject::connect(&spinBox,qOverload<int>(&QSpinBox::valueChanged),&slider,&QSlider::setValue); //需要C++14
QObject::connect(&spinBox,QOverload<int>::of(&QSpinBox::valueChanged),&slider,&QSlider::setValue); //需要C++11
至于信号槽函数带默认参数时,实现方式就用lambda表达式吧。 小白一名帮顶 挺好的一个入门教程,火钳刘明 楼主是要提供资料吗?书? 我一小白,求大佬给个入门C++的好教程,谢谢 lambda 简单调用还行,有时候有坑,比如变量作用域等问题 顶一下! 我看我一年后还会不会看上面的代码, 顶一下! 谢谢楼主分享,
页:
[1]
2