QT ① 概述&信号与槽

一、概述

  • 优良的跨平台特性
  • 面向对象:其中信号与槽替代了回调函数,更加安全(会进行类型检查等)
  • 丰富的API
  • 大量的开发文档

二、命令行程序

  • qmake: Makefile 生成器,能根据工程文件(.pro)产生不同平台下的Makefile
  • uic:把ui文件自动生成相应的C++代码

三、QString类

示例代码:

    qDebug() << "hello world";

    int a = 10 , b = 20;
    //C++ 风格
    qDebug() << "a = " << a << " , b = " << b;

    //C语言风格
    qDebug("a = %d , b = %d",a,b);

    //QString qt中的字符串类
    QString str1 = "12345";
    QString str2("welcome");

    qDebug() << str1 << "  " << str2;

    //qstring 转换 为Int 类型
    int c = str1.toInt();
    qDebug() << c;

    QByteArray arr  = str1.toUtf8();
    qDebug() << arr;

    //QString 的 arg():可以将任意类型的数据转换为 QString 类型
    QString str3 = QString("a: %1, b: %2 , c: %3").arg(a).arg(b).arg(c);
    qDebug() << str3;

    //number():将数值数据转换为QString
    str3 = QString::number(a);
    qDebug() << str3;

    QString str4 = "QString 44444";
    qDebug() << str4.right(2);              //right(n) 取出字符串右边有多少个字符
    qDebug() << str4.left(2);               //取出左边
    qDebug() << str4.mid(2);                //取出中间

    QString str5 = "123,456,789";
    QStringList list = str5.split(",");          //将字符串分割(以逗号分割开)
    qDebug() << list;                               //字符串List容器
    qDebug() << list[0] << "     " << list[2];

输出结果:

hello world
a =  10  , b =  20
a = 10 , b = 20
"12345"    "welcome"
12345
"12345"
"a: 10, b: 20 , c: 12345"
"10"
"44"
"QS"
"tring 44444"
QList("123", "456", "789")
"123"       "789"

四、QT工作原理(事件驱动、信号与槽机制)

  • 1、事件:

    • UI界面或者控件上发生的任何事情,被称为事件。

    • 如:鼠标移动、鼠标点击、控件移动、键盘按压、定时器等,都可以被称为事件触发

  • 2、信号(signals):

    • 信号是一个不完整的函数(只有声明,没有定义)。

    • 一般由系统类库提供,或者由程序员在类体的signals区域声明

    • 信号可以是 事件驱动触发、也可以是程序员代码中手动emit触发

  • 3、槽函数(slots):

    • 是一个完整的成员函数(既有声明,又有定义)。一般由系统类库提供,或者是程序员手动声明在类体的权限区域的slots区域声明
    • 槽函数可以是信号触发后,系统自动调用,也可以是程序员在函数中手动调用
  • 4、事件驱动:

    • UI界面或者控件上产生的任何事情,都会触发一个或者多个信号。
  • 5、信号与槽机制:

    • 将信号与某个槽函数进行关联(绑定、注册),当信号被触发,系统自动调用关联的槽函数。
  • 6、信号与槽的绑定:

    • (1)方法一:ui设计器,鼠标右键转到槽

      槽函数语法:

void on_objectName_signal();
  • ​ (2)方法二:connect函数,手动绑定
 /*
     * 旧风格绑定信号与槽
     *
     * connect(const QObject *sender, const char *signal, const QObject *receiver, const char*member);
     * 功能:
     *          将sender的signal信号 与 receiver的member槽函数关联
     * 参数:
     *          sender:信号触发者首地址
     *          signal:触发的信号首地址
     *          receiver:信号的接收者首地址(槽函数所在的类对象)
     *          member: 要绑定的槽函数首地址
     */
    connect(ui->oldone , SIGNAL(clicked(bool)) , this , SLOT(btn_clicked()));



    /*新风格绑定
     * 安全性更高
     * 信号与槽函数都有类型的说明
    */
    connect(ui->newone , &QPushButton::clicked , this , &SignalSlots::btn_clicked_new);

    /*
     * 匿名函数绑定
     * [] 表示函数名     ()参数列表         {} 函数体
     * & 引用符,表示匿名函数中引用外部的所有成员
     * = 表示匿名函数中拷贝外部的所有成员
     */
    connect(ui->someone , &QPushButton::clicked , this , [&](){
        qDebug() << "匿名绑定";
        speaker.say("哈基米喔,南北绿豆,阿西噶哈,嘻哈亚古");
    });

五、练习(计算器)

UI设计:

alt

源码:

#include "caculater.h"
#include "ui_caculater.h"

Caculater::Caculater(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Caculater)
{
    ui->setupUi(this);
}

Caculater::~Caculater()
{
    delete ui;
}

void Caculater::is_point(QString &str_check)
{
    //先做字符串验证 ,末尾不能是小数点
    if(str_check.at(str_check.length() - 1) == ".")
    {
        str_check.append("0");
    }
}

void Caculater::result()
{
    float res = 0;
    switch(op)
    {
        case DIV:
        {
            res = left / right;
            break;
        }
        case MUL:
        {
            res = left * right;
            break;
        }
        case SUB:
        {
            res = left - right;
            break;
        }
        case ADD:
        {
            res = left + right;
            break;
        }
    }
    QString result = QString::number(res, 'f', 3);
    ui->lineEdit_output->setText(result);
    ui->lineEdit_input->setText("0");
    left = 0;
    right = 0;
    op = NOT_OP;

    QString says;
    if(res < 0)
    {
        says = "等于负";
        res = -res;
        says.append(QString::number(res,'f',3));
    }
    else
    {
        says = "等于";
        says.append(result);
    }
    speaker.say(says);
}


void Caculater::on_btn_num_0_clicked()
{
    //判断是否可以输入0
    if(ui->lineEdit_input->text() == "0")
    {
        return;
    }
    ui->lineEdit_input->insert("0");
    speaker.say("0");
}


void Caculater::on_btn_point_clicked()
{
    //判断是否可以输入小数点
    if(ui->lineEdit_input->text().contains("."))
    {
        return;
    }
    ui->lineEdit_input->insert(".");
    speaker.say("点");
}


void Caculater::on_btn_num_1_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("1");
        speaker.say("1");
        return;
    }
    ui->lineEdit_input->insert("1");
    speaker.say("1");
}


void Caculater::on_btn_num_2_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("2");
        speaker.say("2");
        return;
    }
    ui->lineEdit_input->insert("2");
    speaker.say("2");
}


void Caculater::on_btn_num_3_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("3");
        speaker.say("3");
        return;
    }
    ui->lineEdit_input->insert("3");
        speaker.say("3");
}


void Caculater::on_btn_num_4_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("4");
        speaker.say("4");
        return;
    }
    ui->lineEdit_input->insert("4");
    speaker.say("4");
}


void Caculater::on_btn_num_5_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("5");
        speaker.say("5");
        return;
    }
    ui->lineEdit_input->insert("5");
    speaker.say("5");
}


void Caculater::on_btn_num_6_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("6");
        speaker.say("6");
        return;
    }
    ui->lineEdit_input->insert("6");
    speaker.say("6");
}


void Caculater::on_btn_num_7_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("7");
        speaker.say("7");
        return;
    }
    ui->lineEdit_input->insert("7");
    speaker.say("7");
}


void Caculater::on_btn_num_8_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("8");
        speaker.say("8");
        return;
    }
    ui->lineEdit_input->insert("8");
    speaker.say("8");
}


void Caculater::on_btn_num_9_clicked()
{
    if(ui->lineEdit_input->text() == "0")
    {
        ui->lineEdit_input->setText("9");
        speaker.say("9");
        return;
    }
    ui->lineEdit_input->insert("9");
    speaker.say("9");
}

//清除
void Caculater::on_btn_CLR_clicked()
{
    left = 0;
    right = 0;
    op = NOT_OP;

    ui->lineEdit_input->setText("0");
    ui->lineEdit_output->setText("0");
    speaker.say("归零");
}

//退格操作
void Caculater::on_btn_BS_clicked()
{
    //删除最后一个字符
    ui->lineEdit_input->backspace();
    //退格后没有字符 做归零处理
    if(ui->lineEdit_input->text().length() == 0)
    {
        ui->lineEdit_input->setText("0");
        return;
    }
    speaker.say("退格");
}

//除法
void Caculater::on_btn_div_clicked()
{
    //判断是否已经有运算符
    if(op != NOT_OP)
    {
        return;
    }
    else
    {
        op = DIV;       //除法运算
    }

    QString str_check = ui->lineEdit_input->text();
    //调用小数点检查
    is_point(str_check);
    //存入左数
    left = str_check.toFloat();

    //设置输入栏为0
    ui->lineEdit_input->setText("0");

    str_check.append("÷");
    ui->lineEdit_output->setText(str_check);

    speaker.say("除以");
}


void Caculater::on_btn_mul_clicked()
{
    //判断是否已经有运算符
    if(op != NOT_OP)
    {
        return;
    }
    else
    {
        op = MUL;       //除法运算
    }

    QString str_check = ui->lineEdit_input->text();
    //调用小数点检查
    is_point(str_check);
    //存入左数
    left = str_check.toFloat();

    //设置输入栏为0
    ui->lineEdit_input->setText("0");

    str_check.append("×");
    ui->lineEdit_output->setText(str_check);

    speaker.say("乘以");
}


void Caculater::on_btn_sub_clicked()
{
    //判断是否已经有运算符
    if(op != NOT_OP)
    {
        return;
    }
    else
    {
        op = SUB;       //除法运算
    }

    QString str_check = ui->lineEdit_input->text();
    //调用小数点检查
    is_point(str_check);
    //存入左数
    left = str_check.toFloat();

    //设置输入栏为0
    ui->lineEdit_input->setText("0");

    str_check.append("-");
    ui->lineEdit_output->setText(str_check);

    speaker.say("减");
}


void Caculater::on_btn_add_clicked()
{
    //判断是否已经有运算符
    if(op != NOT_OP)
    {
        return;
    }
    else
    {
        op = ADD;       //除法运算
    }

    QString str_check = ui->lineEdit_input->text();
    //调用小数点检查
    is_point(str_check);
    //存入左数
    left = str_check.toFloat();

    //设置输入栏为0
    ui->lineEdit_input->setText("0");

    str_check.append("+");
    ui->lineEdit_output->setText(str_check);
    speaker.say("加");
}


void Caculater::on_btn_equal_clicked()
{
    if(op == NOT_OP)
        return;
    QString str = ui->lineEdit_input->text();
    is_point(str);
    //右数赋值
    right = str.toFloat();
    //除法判断除数为0
    if(op == DIV && right == 0)
    {
        ui->lineEdit_output->setText("错误:除数为零");
        left = 0;
        right = 0;
        ui->lineEdit_input->setText("0");
        return;
    }
    //计算结果
    result();
}