信號與槽機(jī)制
信號與槽的介紹
- 功能:實(shí)現(xiàn)多個組件之間的相互通信,是QT引以為傲的核心機(jī)制
- 信號:就是信號函數(shù),定義在類體的signals權(quán)限下,是一個不完整的函數(shù),只有聲明沒有定義;
- 槽:就是槽函數(shù),定義在類體的slots權(quán)限下,是一個完整的函數(shù),既有聲明也有定義,也可以當(dāng)做普通函數(shù)被使用
- 無論信號函數(shù)還是槽函數(shù),返回值一般都是void類型,參數(shù)可以自定義,參數(shù)的目的就是為了傳遞信息
- 包含信息與槽定義的類體
class Widget : public QWidget
{
Q_OBJECT //信號與槽的元對象
signals:
void my_signal(); //自定義信號函數(shù)
public slots:
void my_slot(); //自定義的槽函數(shù)
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
信號與槽的連接
- 在ui界面下的信號與槽的編輯處進(jìn)行連接,該連接方式只能發(fā)射系統(tǒng)提供的信號,并使用系統(tǒng)提供的槽函數(shù)
- 在ui界面的組件上,右鍵轉(zhuǎn)到槽,選擇信號,槽函數(shù)邏輯需要自行書寫
qt4版本的連接函數(shù)(書寫錯誤不會報錯)
[static] QMetaObject::Connection //返回值是一個連接,并且該函數(shù)是一個靜態(tài)成員函數(shù)
QObject::connect( //函數(shù)名
const QObject *sender, //信號的發(fā)射者,是組件的指針
const char *signal, //要發(fā)射的信號是一個C語言風(fēng)格的字符串,將信號函數(shù)傳遞進(jìn)來時,需要使用SIGNAL宏進(jìn)行轉(zhuǎn)換
const QObject *receiver, //信號的接受者,是組件的指針
onst char *method) //處理信號的槽函數(shù),是C風(fēng)格字符串,將槽函數(shù)傳遞進(jìn)來時,需要使用SLOT宏進(jìn)行轉(zhuǎn)換
注意:信號函數(shù)必須是信號的發(fā)射者所在的類中有的信號函數(shù),而槽函數(shù)也必須是信號的接受者中有的槽函數(shù)
舉個例子:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)));
qt5版本的連接函數(shù)
[static] QMetaObject::Connection //返回值是一個連接,并且該函數(shù)是一個靜態(tài)成員函數(shù)
QObject::connect( //函數(shù)名
const QObject *sender, //信號的發(fā)射者,是組件的指針
PointerToMemberFunction signal, //信號函數(shù)的函數(shù)指針變量,直接填寫函數(shù)名即可
const QObject *receiver, //信號的接受者,是組件的指針
PointerToMemberFunction method) //槽函數(shù)的函數(shù)指針變量,直接填寫函數(shù)名即可
舉個例子:
QLabel *label = new QLabel;
QLineEdit *lineEdit = new QLineEdit;
QObject::connect(lineEdit, &QLineEdit::textChanged,
label, &QLabel::setText);
信號連接外部函數(shù)或lambda表達(dá)式
[static] QMetaObject::Connection //返回值是一個連接,并且該函數(shù)是一個靜態(tài)成員函數(shù)
QObject::connect( //函數(shù)名
const QObject *sender, //信號的發(fā)射者,是組件的指針
PointerToMemberFunction signal, //信號函數(shù)的函數(shù)指針變量,直接填寫函數(shù)名即可
Functor functor) //處理信號的功能函數(shù),可以是全局函數(shù),也可以是lambda表達(dá)式
舉個例子:
void someFunction();
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::clicked, someFunction);
Lambda 表達(dá)式作為槽函數(shù):
QByteArray page = ...;
QTcpSocket *socket = new QTcpSocket;
socket->connectToHost("qt-project.org", 80);
QObject::connect(socket, &QTcpSocket::connected, [=] () {
socket->write("GET " + page + "\r\n");
});
斷開信號與槽的連接
只需將上面的連接函數(shù)前加dis即可,參數(shù)都不變
發(fā)射自定義信號
- 在自定義類體內(nèi)的signals權(quán)限下,定義自定義的信號函數(shù),返回值為void,可以有參數(shù),也可以沒參數(shù)
- 在程序所需處,使用關(guān)鍵字emit發(fā)射自定義的信號:emit 信號名(實(shí)參列表);
- 將自定義的信號與槽函數(shù)進(jìn)行連接
- 當(dāng)自定義的信號發(fā)射后,槽函數(shù)會立即響應(yīng)
信號與槽函數(shù)總結(jié)
- 一個信號可以連接到多個槽函數(shù)中,當(dāng)信號被發(fā)射后,與之連接的所有槽函數(shù)都會被執(zhí)行
- 一個槽函數(shù)可以連接多個信號函數(shù),但凡其中一個信號被發(fā)射,那么槽函數(shù)就會被執(zhí)行
- 一個信號函數(shù),也可以連接到另一個信號函數(shù)上,表明當(dāng)一個信號發(fā)射時,后一個信號跟著被發(fā)射
信號函數(shù)與槽函數(shù)參數(shù)個數(shù)總結(jié)
1、信號函數(shù)和槽函數(shù)進(jìn)行鏈接時,一般要求信號函數(shù)和槽函數(shù)的參數(shù)保持一致
connect(信號發(fā)送者, SIGNAL(signalFun()),信號接收者, SLOT(slotFun())); //Ok
connect(信號發(fā)送者, SIGNAL(signalFun(int)),信號接收者, SLOT(slotFun(int))); //Ok
connect(信號發(fā)送者, SIGNAL(signalFun(int, char)),信號接收者, SLOT(slotFun(int, char))); //Ok
connect(信號發(fā)送者, SIGNAL(signalFun(char, int)),信號接收者, SLOT(slotFun(int, char))); //False
connect(信號發(fā)送者, SIGNAL(signalFun(int)),信號接收者, SLOT(slotFun(char))); //False
2、當(dāng)信號函數(shù)的參數(shù)大于槽函數(shù)的參數(shù)時
connect(信號發(fā)送者, SIGNAL(signalFun(int, char)),信號接收者, SLOT(slotFun())); //Ok
connect(信號發(fā)送者, SIGNAL(signalFun(int, char)),信號接收者, SLOT(slotFun(int))); //Ok
connect(信號發(fā)送者, SIGNAL(signalFun(int, char)),信號接收者, SLOT(slotFun(char))); //False
3、當(dāng)信號函數(shù)的參數(shù)小于槽函數(shù)的參數(shù)時
connect(信號發(fā)送者, SIGNAL(signalFun(int)),信號接收者, SLOT(slotFun(int, char))); //False
connect(信號發(fā)送者, SIGNAL(signalFun(int)),信號接收者, SLOT(slotFun(int, char=0))); //Ok
練習(xí)
完成登錄框的按鈕操作,并在登錄成功后進(jìn)行界面跳轉(zhuǎn)
.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
signals:
void my_signal();
void jump();
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void my_slot();
void on_clicked();
private:
Ui::MainWindow *ui;
QPushButton *btn1;
QPushButton *btn2;
QLabel *lab1;
QLineEdit * edit1;
QLineEdit * edit2;
};
#endif // MAINWINDOW_H
/*********************************************************************/
//第二個界面
#ifndef FORM_H
#define FORM_H
#include <QWidget>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr);
~Form();
public slots:
void jump_slot();
private:
Ui::Form *ui;
};
#endif // FORM_H
.cpp文件
#include "mainwindow.h"
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <cstring>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//設(shè)置窗口
this->resize(540,410); //設(shè)置窗口大小
this->setWindowTitle("奕書聊天室");//設(shè)置窗口標(biāo)題
this->setWindowIcon(QIcon(":/wodepeizhenshi.png"));
//設(shè)置登錄按鈕組件
btn1 = new QPushButton(QIcon(":/login.png"),
"登錄",
this);//設(shè)置按鈕組件的圖標(biāo),文本內(nèi)容,和讓其在當(dāng)前界面顯示
btn1->move(240,340); //設(shè)置按鈕組件的位置
btn1->resize(80,40); //設(shè)置按鈕組件的大小
// btn1->setEnabled(false); //設(shè)置按鈕不可點(diǎn)擊
//連接登錄按鈕
connect(btn1,&QPushButton::clicked, this, &MainWindow::my_slot);
connect(btn1,&QPushButton::clicked, this, &MainWindow::on_clicked);
//設(shè)置取消按鈕組件
btn2 = new QPushButton(QIcon(":/cancel.png"),
"取消",
this);//設(shè)置按鈕組件的圖標(biāo),文本內(nèi)容,和讓其在當(dāng)前界面顯示
btn2->move(340,340);
btn2->resize(80,40);
// btn2->setEnabled(false);
//連接取消登錄按鈕
connect(btn2,SIGNAL(pressed()),this,SLOT(close()));
//設(shè)置LOGO
lab1 = new QLabel(this);
lab1->setPixmap(QPixmap(":/logo.png"));
lab1->resize(540,180);
lab1->setScaledContents(true);
//設(shè)置行編輯器 賬號
edit1 = new QLineEdit(this);
edit1->resize(220,40);
edit1->move(180,220);
edit1->setPlaceholderText("QQ號碼/手機(jī)/郵箱");//設(shè)置占位符
//edit1->setEchoMode(QLineEdit::Password);
//設(shè)置行編輯器 密碼
edit2 = new QLineEdit(this);
edit2->resize(220,40);
edit2->move(180,280);
edit2->setPlaceholderText("密碼");//設(shè)置占位符
edit2->setEchoMode(QLineEdit::Password);//設(shè)置密文顯示
//設(shè)置賬號的LOGO
QLabel *lab2 = new QLabel(this);
lab2->setPixmap(QPixmap(":/userName.jpg"));
lab2->resize(50,40);
lab2->move(edit1->x()-85,edit1->y());
lab2->setScaledContents(true); //設(shè)置圖片內(nèi)容自適應(yīng)
//設(shè)置賬號的LOGO
QLabel *lab3 = new QLabel(this);
lab3->setPixmap(QPixmap(":/passwd.jpg"));
lab3->resize(50,40);
lab3->move(edit2->x()-85,edit2->y());
lab3->setScaledContents(true); //設(shè)置圖片內(nèi)容自適應(yīng)
}
MainWindow::~MainWindow()
{
}
void MainWindow::my_slot()
{
if(edit1->text()=="admin" && edit2->text()=="123456")
{
qDebug()<<"登錄成功";
this->close();
}
else
{
qDebug()<<"登錄失敗";
edit2->clear();
}
}
void MainWindow::on_clicked()
{
emit jump();
}
/********************************************************************/
//第二個界面
#include "form.h"
#include "ui_form.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
}
Form::~Form()
{
delete ui;
}
void Form::jump_slot()
{
this->show();
}
面試小測
多態(tài),虛函數(shù),純虛函數(shù)
-
類的三大屬性:多態(tài),封裝,繼承;多態(tài)也就是一種形式的多種狀態(tài),多態(tài)又分為靜態(tài)多態(tài)和動態(tài)多態(tài),函數(shù)重載時就屬于靜態(tài)多態(tài),而運(yùn)行時屬于動態(tài)多態(tài);多態(tài)又是父類的指針或者引用指向或初始化子類對象,調(diào)用子類對父類重寫的函數(shù),進(jìn)而展開子類的功能
-
虛函數(shù)用virtual修飾的函數(shù)即為虛函數(shù),當(dāng)類中存在虛函數(shù),那么該類中就會有一個虛指針,虛指針指向虛函數(shù)表,虛函數(shù)表中記錄了所有虛函數(shù)以及子類對父類重寫的函數(shù)。文章來源:http://www.zghlxwxcb.cn/news/detail-691166.html
-
純虛函數(shù):當(dāng)父類中的虛函數(shù)沒有實(shí)際意義時,可將該虛函數(shù)設(shè)置為純虛函數(shù),含有純虛函數(shù)的類被稱為抽象類,抽象類不能實(shí)例化對象,當(dāng)子類沒有對父類的純虛函數(shù)進(jìn)行重新時,子類也被稱為抽象類。文章來源地址http://www.zghlxwxcb.cn/news/detail-691166.html
將“引用”作為函數(shù)參數(shù)有哪些特點(diǎn)
- 函數(shù)參數(shù)是程序間數(shù)據(jù)交互的橋梁,一般分為值傳遞和地址傳遞。值傳遞,傳遞的是值,不改變值原本的大小。地址傳遞,傳遞的是地址,當(dāng)通過地址訪問到其地址所指向的內(nèi)容時,其內(nèi)容可以發(fā)生改變。引用的實(shí)質(zhì)為取別名,一旦確定指向不能更改。使用引用作為函數(shù)參數(shù)時,不需要重新開辟空間,效率高,通過引用可直接改變其對應(yīng)的內(nèi)容。當(dāng)引用不想被改變的變量時,可使用const修飾,此時為常引用,常引用不能修改值的大小。
結(jié)構(gòu)與聯(lián)合的區(qū)別
- 結(jié)構(gòu)體與聯(lián)合體都是構(gòu)造數(shù)據(jù)類型,都是由相同或不同的數(shù)據(jù)類型構(gòu)造而成。但是結(jié)構(gòu)體每個成員地址連續(xù),結(jié)構(gòu)體大小由每個成員的字節(jié)大小字節(jié)對齊原則決定。而聯(lián)合體大小由其成員中字節(jié)最大的決定,所有成員共用一片空間。
到了這里,關(guān)于QT中信號與槽機(jī)制的介紹,以及信號與槽連接的幾種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!