QT开发(二)(信号和槽)

QT开发

    • 标准信号和槽
    • 自定义槽
    • 带参信号
    • Lambda表达式
    • 代码

标准信号和槽

—main.cpp如图所示,诸多的控件应该在主窗口中去实现而不应在主函数中实现

QT开发(二)(信号和槽)_第1张图片
—改变编码
TOOLS—>options—>TextEditor—>behavor—>file coding 选择Utf-8—>apply—>OK

—设置控件

MainWdiget.h

private:
    QPushButton b1;//对象
    QPushButton *b2;//指针方式
    QPushButton b3;

在MainWidget.cpp实现

  b1.setParent(this);
  b1.setText("close");
  b1.move(100, 100);
  
  b2 = new QPushButton(this);//注意指针需要动态分配空间,否则会发生段错误
  b2->setText("abc");

至此可以在主窗口上显示两个按键

—实现点击b1就会关闭主窗口

如何查看一个类帮助文档:点击类名,按F1(按两次全屏显示帮助文档),如果没有发现signal,则去查看其基类(Inherits)的signals

QT开发(二)(信号和槽)_第2张图片
QPushbutton帮助文档无信号,其基类的信号如图所示

    b1.setParent(this);
    b1.setText("close");
    b1.move(100, 100);
    
    connect(&b1, &QPushButton::pressed, this, &MainWidget::close);
    /* &b1: 信号发出者,指针类型
     * &QPushButton::pressed:处理的信号,  &发送者的类名::信号名字
     * this: 信号接收者
     * &MainWidget::close: 槽函数,信号处理函数  &接收的类名::槽函数名字
    */

自定义槽

自定义槽的用法与普通函数的用法一样,Qt5中自定义槽可以是任意的成员函数,普通全局函数,静态函数。槽函数需要和信号一致(参数,返回值),信号是没有返回值的,故槽函数没有返回值

—通过点击b2将控件名字改变

 connect(b2, &QPushButton::released, this, &MainWidget::mySlot);//b2是指针,不用取地址
 
 写自定义槽函数时,一般写成共有的成员函数
 MainWidget.h
  void mySlot();//声明自定义槽函数 
  
 MainWidget.cpp
 void MainWidget::mySlot()
{
    b2->setText("123");
}

—通过点击抬起后b2使b1隐藏

MainWidget.cpp

connect(b2, &QPushButton::released, &b1, &QPushButton::hide);

—主窗口和 窗口切换

新建一个子窗口:

点击工程目录—>ADD NEW—>C++ CLASS—>命名为SubWidget基类选择为窗口类
添加一个按钮:在SubWidget.h中
private
QPushButton b;

SubWidget.cpp
    this->setWindowTitle("son");
    b.setParent(this);
    b.setText("切换到主窗口");
在主窗口设置一个按钮
    b3.setParent(this);
     setWindowTitle("father");//this—>setWindowTitle("father")也可以
    b3.setText("切换到子窗口");
    b3.move(50, 50);

注意,在设置完该子窗口后RUN并不会显示两个独立窗口,应该将SubWidget.h包含到MainWidget.h中并定义一个对象w(private: SubWidget w;),然后在MainWidget.cpp中w.show()即可显示出两个独立窗口

MainWidget.h
public :
void changeWin();

MainWidget.cpp
 connect(&b3, &QPushButton::released, this, &MainWidget::changeWin);


void MainWidget::changeWin()
{
  //子窗口显示
    subWin.show();
    //本窗口隐藏
    this->hide();
}

此时RUN,点击b3会显示子窗口w但是点击子窗口无反应,解决思路:在子窗口按下按钮后发出一个信号由主窗口处理

SubWidget.h
signals:
     /* 信号必须有signals关键字来声明
      * 信号没有返回值,但可以有参数
      * 信号就是函数的声明,只需声明,无需定义
      * 信号的使用:emit mySignal();
      * 信号可以重载
     */
    void mySignal();
 SubWidget.cpp
  connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot);

void SubWidget::sendSlot()
{
  emit mySignal();
}
MainWidget.cpp

connect(&w,&SubWidget::mySignal,this,&MainWidget::dealSub);


void MainWidget::dealSub()
{
    //子窗口隐藏
    subWin.hide();
    //本窗口显示
    show();
}

至此可以通过点击按钮实现两个窗口之间的切换

带参信号

信号重载
函数指针
正确输出QString

SubWidget.cpp
//将mySignal()重载,产生一个带参信号
void SubWidget::sendSlot()
{
    emit mySignal();
    emit mySignal(250, "我是子窗口");//切换子窗口时打印内容
}
MMainWidget.h
//在头文件中声明
void dealSlot();



MainWidget.cpp
  /*//之前也定义过一次,故会产生二义性,应该使用函数指针解决
connect(&w,&SubWidget::mySignal,this,&MainWidget::dealSub);
connect(&w,&SubWidget::mySignal,this,&MainWidget::dealSlot)*/

 void (SubWidget::*funSignal)() = &SubWidget::mySignal;
connect(&subWin, funSignal, this, &MainWidget::dealSub);


  void (SubWidget::*testSignal)(int, QString) = &SubWidget::mySignal;
  connect(&subWin, testSignal, this, &MainWidget::dealSlot);

void MainWidget::dealSlot(int a, QString str)
{
    // str.toUtf8() 转换成字节数组QByteArray
    // ……data()  将 QByteArray 转换成 char *可以输出
    qDebug() << a << str.toUtf8().data();

Lambda表达式

匿名函数对象
C++11新增加特性,需要在项目文件(.proc)加上 CONFIG += C++11

 QPushButton *b4 = new QPushButton(this);
    b4->setText("Lambda表达式");
    b4->move(150, 150);
    int a = 10, b = 100;
    connect(b4, &QPushButton::clicked,
            // = :把外部所有局部变量、类中所有成员以值传递方式,最常用
            // this: 类中所有成员以值传递方式
            // & : 把外部所有局部变量, 引用符号
            [=](bool isCheck)
            {
                 b4—>setText("123")
                qDebug() << isCheck;
                qDebug() << a<

代码

MainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H


#include 
#include 
#include "subwidget.h" //子窗口头文件


class MainWidget : public QWidget
{
    Q_OBJECT


public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();


public slots:
    void mySlot();
    void changeWin();
    void dealSub();
    void dealSlot(int, QString);


private:
    QPushButton b1;
    QPushButton *b2;
    QPushButton b3;


    SubWidget subWin;
};


#endif // MAINWIDGET_H
SubWidget.h

#ifndef SUBWIDGET_H
#define SUBWIDGET_H


#include 
#include 


class SubWidget : public QWidget
{
    Q_OBJECT
public:
    explicit SubWidget(QWidget *parent = 0);


    void sendSlot();


signals:
     /* 信号必须有signals关键字来声明
      * 信号没有返回值,但可以有参数
      * 信号就是函数的声明,只需声明,无需定义
      * 使用:emit mySignal();
      * 信号可以重载
     */


    void mySignal();
    void mySignal(int, QString);


public slots:


private:
    QPushButton b;
};


#endif // SUBWIDGET_H
MainWidget.cpp

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    b1.setParent(this);
    b1.setText("close");
    b1.move(100, 100);


    b2 = new QPushButton(this);
    b2->setText("abc");


    connect(&b1, &QPushButton::pressed, this, &MainWidget::close);
    /* &b1: 信号发出者,指针类型
     * &QPushButton::pressed:处理的信号,  &发送者的类名::信号名字
     * this: 信号接收者
     * &MainWidget::close: 槽函数,信号处理函数  &接收的类名::槽函数名字
    */


    /* 自定义槽,普通函数的用法
     * Qt5:任意的成员函数,普通全局函数,静态函数
     * 槽函数需要和信号一致(参数,返回值)
     * 由于信号都是没有返回值,所以,槽函数一定没有返回值
     */
    connect(b2, &QPushButton::released, this, &MainWidget::mySlot);


    connect(b2, &QPushButton::released, &b1, &QPushButton::hide);


    /* 信号:短信
     * 槽函数:接收短信的手机
     */


    setWindowTitle("老大");
    //this->setWindowTitle("老大");


    b3.setParent(this);
    b3.setText("切换到子窗口");
    b3.move(50, 50);


    //显示子窗口
    //subWin.show();


    connect(&b3, &QPushButton::released, this, &MainWidget::changeWin);




    //处理子窗口的信号
//    void (SubWidget::*funSignal)() = &SubWidget::mySignal;
//    connect(&subWin, funSignal, this, &MainWidget::dealSub);


//     void (SubWidget::*testSignal)(int, QString) = &SubWidget::mySignal;
//    connect(&subWin, testSignal, this, &MainWidget::dealSlot);


    //Qt4信号连接
    //Qt4槽函数必须有slots关键字来修饰
    connect(&subWin, SIGNAL(mySignal()), this, SLOT(dealSub()) );


    connect(&subWin, SIGNAL(mySignal(int,QString)),
            this, SLOT(dealSlot(int,QString)) );
    // SIGNAL SLOT 将函数名字 -> 字符串  不进行错误检查


    //Lambda表达式, 匿名函数对象
    //C++11增加的新特性, 项目文件: CONFIG += C++11
    //Qt配合信号一起使用,非常方便


    QPushButton *b4 = new QPushButton(this);
    b4->setText("Lambda表达式");
    b4->move(150, 150);
    int a = 10, b = 100;
    connect(b4, &QPushButton::clicked,
            // = :把外部所有局部变量、类中所有成员以值传递方式
            // this: 类中所有成员以值传递方式
            // & : 把外部所有局部变量, 引用符号
            [=](bool isCheck)
            {
                qDebug() << isCheck;
            }




            );




    resize(400, 300);
}


void MainWidget::dealSlot(int a, QString str)
{
    // str.toUtf8() -> 字节数组QByteArray
    // ……data()  -> QByteArray -> char *
    qDebug() << a << str.toUtf8().data();
}


void MainWidget::mySlot()
{
    b2->setText("123");
}


void MainWidget::changeWin()
{
    //子窗口显示
    subWin.show();
    //本窗口隐藏
    this->hide();
}




void MainWidget::dealSub()
{
    //子窗口隐藏
    subWin.hide();
    //本窗口显示
    show();
}


MainWidget::~MainWidget()
{


}
SubWidget.cpp
#include "subwidget.h"


SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
    this->setWindowTitle("小弟");
    b.setParent(this);
    b.setText("切换到主窗口");


    connect(&b, &QPushButton::clicked, this, &SubWidget::sendSlot);


    resize(400, 300);
}


void SubWidget::sendSlot()
{
    emit mySignal();
    emit mySignal(250, "我是子窗口");
}·

你可能感兴趣的:(QT开发)