QT入门笔记
Qt事件
Qt 事件指的是应用程序和用户之间的交互过程,例如用户按下某个按钮,点击某个输入框等等。实际上除了用户会与应用程序进行交互外,操作系统也会与应用程序进行交互,例如当某个定时任务触发时,操作系统会关闭应用程序,这也是一个事件。
Qt 界面程序的 main() 主函数中首先要创建一个 QApplication 类的对象,函数执行结束前还要调用 QApplication 对象的 exec() 函数。一个 Qt 界面程序要想接收事件,main() 函数中就必须调用 exec() 函数,它的功能就是使程序能够持续不断地接收各种事件。
信号和槽介绍
信号(Signal):就是在特定情况下被发射的事件,例如PushButton 最常见的信号就是鼠标单击时发射的 clicked() 信号,一个 ComboBox 最常见的信号是选择的列表项变化时发射的 CurrentIndexChanged() 信号。GUI 程序设计的主要内容就是对界面上各组件的信号的响应,只需要知道什么情况下发射哪些信号,合理地去响应和处理这些信号就可以了。
槽(Slot):就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。
connect
[static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection);
第一个参数发送者,第二个信号,第三个接收者,第四个接收者的响应函数,第五个信号与槽的连接方式
Q_OBJECT:本质是一个已定义好的宏,所有需要“信号和槽”功能的组件都必须将 Q_OBJECT 作为 private 属性成员引入到类中。
QT信号和槽
在 Qt 中,用户和控件的每次交互过程称为一个事件,比如“用户点击按钮”是一个事件,“用户关闭窗口”也是一个事件。每个事件都会发出一个信号,例如用户点击按钮会发出“按钮被点击”的信号,用户关闭窗口会发出“窗口被关闭”的信号。
Qt 中的所有控件都具有接收信号的能力,一个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到“按钮被点击”的信号后,会做出“关闭自己”的响应动作;再比如输入框自己接收到“输入框被点击”的信号后,会做出“显示闪烁的光标,等待用户输入数据”的响应动作。在 Qt 中,对信号做出的响应动作就称为槽。
信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:
- 信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰。signals 和 slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;
- 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。
新版 connect() 函数指定信号函数和槽函数的语法格式是&+函数所在类+函数名
,一个 connect() 函数只能关联一个信号函数和一个槽函数
自定义信号和槽
自定义信号函数
信号函数指的是符合以下条件的函数:
- 定义在某个类中,该类直接或间接继承自 QObject 类;
- 用 signals 关键字修饰;
- 函数只需要声明,不需要定义(实现);
- 函数的返回值类型为 void,参数的类型和个数不限。
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QDebug>
#include <QLabel>
#include <QPushButton>
class MyWidget:public QWidget{
//Q_OBJECT 是一个宏,添加它才能正常使用 Qt 的信号和槽机制
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
~MyWidget();
//修饰信号函数的关键字
signals:
//自定义的信号函数
void MySignal(QString message, QString mess2);
public:
void emitSignal(){
qDebug() << "qDebug输出";
emit MySignal(message1, message2); //自定义语句就表示发射 MySignal 信号
}
//类的成员函数
void recSlot1(QString mess){
qDebug() << "执行 recSlot1() 成员函数,输出" << mess;
}
//指明定义的是槽函数
public slots:
void mySlot();
void recSlot2(QString mess1,QString mess2){
qDebug() << "执行 recSlot2() 槽函数,输出"<< mess1 << " " << mess2;
}
public:
QString message1;
QString message2;
QPushButton b1;
QPushButton *b2;
};
//全局函数
/*void recSlot3(){
qDebug() << "执行 recSlot3() 全局函数";
}*/
#endif // MYWIDGET_H
自定义槽函数
Qt5 中,槽函数既可以是普通的全局函数、也可以是类的成员函数、静态成员函数、友元函数、虚函数,还可以用 lambda 表达式表示。
和信号函数不同,槽函数必须手动定义(实现)。槽函数可以在程序中直接调用,但主要用来响应某个信号。自定义一个槽函数时,需要注意以下几点:
- 槽函数的返回值必须和信号函数相同,由于信号函数的返回值一定是 void,所以槽函数的返回值也必须为 void;
- 对于带参的信号函数,槽函数可以选择接收所有参数,则参数的类型、顺序、个数都必须与信号函数相同;也可以选择接收前几个参数,这些参数的类型、顺序都必须与信号函数相同;还可以选择不接受任何参数。
- 槽函数的参数个数只能比信号函数少,不能比信号函数多;
- 槽函数的参数不能有默认值。
#include "MyWidget.h"
MyWidget::MyWidget(QWidget *parent) : QWidget(parent){
b1.setParent(this);
b1.setText("Close");
b1.move(50, 50);
b2 = new QPushButton(this);
b2->setText("Button2");
b2->move(150, 50);
connect(&b1, &QPushButton::clicked, this, &MyWidget::close);
connect(b2, &QPushButton::clicked, this, &MyWidget::mySlot); //关联自身的槽函数
}
void MyWidget::mySlot()
{
b2->setText("^_^");
}
MyWidget::~MyWidget()
{
}
#include "mainwindow.h"
#include "MyWidget.h"
#include <QApplication>
#include <QLocale>
#include <QTranslator>
#include <QtCore>
#include <QPushButton>
#include <QWidget>
//全局函数
void recSlot3(){
qDebug() << "执行 recSlot3() 全局函数";
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) {
const QString baseName = "test1_" + QLocale(locale).name();
if (translator.load(":/i18n/" + baseName)) {
a.installTranslator(&translator);
break;
}
}
//创建主窗口
MyWidget mywidget;
//类的成员函数作为槽函数
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot1);
//信号函数和槽函数相连接
QObject::connect(&mywidget,&MyWidget::MySignal,&mywidget,&MyWidget::recSlot2);
//全局函数作为槽函数
QObject::connect(&mywidget,&MyWidget::MySignal,&recSlot3);
mywidget.show();
//QThread::sleep(5000);
//发射 Signal 信号
//mywidget.emitSignal();
return a.exec();
}