1、凡是QObject
类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。
许多初学者会遇到莫名其妙的错误,一加上Q_OBJECT
就出错,很大一部分是因为没有注意到这个宏应该放在头文件中
这个宏的展开将为我们的类提供信号槽机制、国际化机制以及 Qt 提供的不基于 C++ RTTI 的反射能力。
2、可以lambda表达式来替代槽函数。
3、
(1)、在QT5中,槽函数可以不放在由slots修饰的代码块中。
//!!! Qt5
#include
// newspaper.h
class Newspaper : public QObject
{
Q_OBJECT
public:
Newspaper(const QString & name) :
m_name(name)
{
}
void send()
{
emit newPaper(m_name);
}
signals:
void newPaper(const QString &name);
private:
QString m_name;
};
// reader.h
#include
#include
class Reader : public QObject
{
Q_OBJECT
public:
Reader() {}
void receiveNewspaper(const QString & name)
{
qDebug() << "Receives Newspaper: " << name;
}
};
// main.cpp
#include
#include "newspaper.h"
#include "reader.h"
int main(int argc, char *argv[]) //将执行程序时的两个命令行参数传入
{
QCoreApplication app(argc, argv); //实例化一个应用
Newspaper newspaper("Newspaper A");
Reader reader;
QObject::connect(&newspaper, &Newspaper::newPaper,
&reader, &Reader::receiveNewspaper);
newspaper.send();
return app.exec();
}
(2)在 Qt 4 中,槽函数必须放在由 slots 修饰的代码块中,并且要使用访问控制符进行访问控制。其原则同其它函数一样:默认是 private 的,如果要在外部访问,就应该是 public slots;如果只需要在子类访问,就应该是 protected slots。
//!!! Qt4
#include
// newspaper.h
class Newspaper : public QObject
{
Q_OBJECT
public:
Newspaper(const QString & name) :
m_name(name)
{
}
void send() const
{
emit newPaper(m_name);//const函数不能调用非const函数
}
signals:
void newPaper(const QString &name) const;
private:
QString m_name;
};
// reader.h
#include
#include
class Reader : public QObject
{
Q_OBJECT
public:
Reader() {}
public slots:
void receiveNewspaper(const QString & name) const
{
qDebug() << "Receives Newspaper: " << name;
}
};
// main.cpp
#include
#include "newspaper.h"
#include "reader.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Newspaper newspaper("Newspaper A");
Reader reader;
QObject::connect(&newspaper, SIGNAL(newPaper(QString)),
&reader, SLOT(receiveNewspaper(QString)));
//QObject::connect(&newspaper, SIGNAL(newPaper(const QString)&),
// &reader, SLOT(receiveNewspaper(const QString&)));
newspaper.send();
return app.exec();
}
(3)成员初始化列表
Newspaper(const QString & name):m_name(name)
C++ 语法, m_name(name) 作用相当于在构造函数中添加这么一句:m_name = name。但是,初始化列表的执行是在构造函数的实际语句之前进行的。
另外,构造函数为什么要使用const QString & name?这是标准C++中的内容,表明该参数是一个引用,并且函数不改变参数的值。
(4)槽函数修饰public、private等
public、private 这样的访问修饰符是供编译器检查的,对于运行期连接的信号槽,不会受到这些修饰符的影响。
在qt5中,作为槽,始终是public的;
在qt4中,connect()函数中使用成员函数作为槽函数时,会无视 private 限定符(即,你可以在 connect() 函数中将信号与 private 的槽函数连接起来,这不会报错)。当然,你也可以使用 private 修饰槽函数,只是这个 private 修饰符只在直接调用函数时起作用。
(5)QApplication:QCoreAppilication:QObject
QApplication:支持GUI应用
QCoreApplication:仅仅支持控制台应用
新建GUI项目时,会在main.cpp中自动生成:
QApplication app(argc,argv);
(6)
Qt 4 的 SLOT 和 SIGNAL 宏在处理之前有一个“标准化”的步骤,会将参数的 const 和引用都去除,只有一个最简单的类型作为参数,所以下面两种写法的结果其实是一样的。
QObject::connect(&newspaper, SIGNAL(newPaper(QString)),
&reader, SLOT(receiveNewspaper(QString)));
与
QObject::connect(&newspaper, SIGNAL(newPaper(const QString)&),
&reader, SLOT(receiveNewspaper(const QString&)));
4、 QT控制台与纯 C/C++ 的控制台程序的区别
他们的一个很大的区别在 main()
函数的最后一句:return a.exec();
。
Qt 会开启一个事件循环,监听程序发出的事件;普通 C/C++ 控制台程序,除非你自己编写事件循环,否则是没有这个实现的。
5、qt项目路径不允许出现中文
6、用QT创建了A、B两个窗体,准备把B中的信号发到A中的槽里,若不适用主函数,则应该把connect函数写在哪里?
信号槽主要用于解耦,发出信号的对象不应该知道是谁使用了这个信号;基于这个原则,connect() 函数应该在槽函数的类中。所以按照这个案例,应该是在 A 中更合适一些。
7、信号和槽的参数传递的机制
(1)当信号与槽函数的参数数量相同时,它们参数类型要完全一致。
(2)当信号的参数与槽函数的参数数量不同时,只能是信号的参数数量多于槽函数的参数数量,且前面相同数量的参数类型应一致,信号中多余的参数会被忽略。
(3)此外,在不进行参数传递时,信号槽绑定时也是要求信号的参数数量大于等于槽函数的参数数量。这种情况一般是一个带参数的信号去绑定一个无参数的槽函数。