信号与槽与简易计算器

目录

一、什么是信号与槽

二、信号与槽如何关联

三、需要知道的一些规则

简易计算器的实现

 代码展示

widget.h

main.cpp

widget.cpp

widget.ui

 运行展示

 遇到的问题


 

信号与槽(Signal & Slot)是Qt编程的基础,也是Qt的一大创新。

 

一、什么是信号与槽

信号(Signal)就是在特定情况下被发射的事件,例如PushButton常见的信号就是鼠标单击时发射的clicked()信号,而一个ComboBox最常见的信号是选择的列表项变化时发射的CurrentIndexChanged()信号。GUI程序设计的主要内容就是对界面各组件的信号响应,只要知道什么情况发射哪些信号,然后合理去响应和处理这些信号就好了。

槽(Slot)就是对信号响应的函数。与一般的C++函数一样,槽就是一个函数,可以定义在类的任何部分(如public、private或protected),可以具有任意参数,也可以被直接调用。与一般函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数自动被执行。

 

信号与槽的关系

二、信号与槽如何关联

信号与槽的关联是用QObject::connect()函数实现的。connect()是QObject类的一个静态函数,而QObject是所有Qt类的基类。在实际调用时也可以忽略前面的限定符,直接调用connect。

(1)在Qt5之前的版本中connect的基本格式是:

QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

其中sender是发射信号的对象名称,signal()是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时需要指明参数。receiver是接收信号的对象名称,slot()是槽函数的名称。比如以下代码:

QObject::connect(pushButton, SIGNAL(clicked()), widget, SLOT(close()));

实现了“点击按钮关闭窗口”的功能。

(2)从Qt5.0版本开始,connect函数引入了新的用法(原来的方法正常使用),改进了指定信号函数和槽函数的方式,不再使用SIGNAL()和SLOT()宏,而是采用“&函数所在类名::函数名”的格式。比如上面的例子在新用法中是,

QObject::connect(pushButton, &QPushButton::clicked, widget, &QWidget::close);

(3)默认地,Qt在每一个setupUi函数中包含了如下的关联函数,

QMetaObject::connectSlotsByName(QObject *object);

功能是递归搜索给定object对象的所有子对象,并将来自这些子对象的匹配信号关联到以下形式的槽函数:“on_子对象名称_信号名”。比如你自己定义了一个函数,

void on_pushButton_clicked();

那么这个函数将作为槽函数自动关联到pushButton的clicked()信号,而不再需要显式地调用connect函数。

 

 

灵活的关联方式

三、需要知道的一些规则

(1)一个信号可以关联多个槽,槽函数按照建立连接时的顺序依次执行。

(2)多个信号可以连接同一个槽,任意一个信号被发射时都会触发槽函数。

(3)一个函数被发射时,与其关联的槽函数通常被立即执行。只有当信号关联的所有槽函数都执行完毕后,才会执行发射信号处后面的代码。

(4)一个信号可以连接另外一个信号,只需将SLOT(slot())替换为被连接的信号SINGAL(signal2())。这样,当一个信号被发射时,也会发射另外一个信号,实现某些特殊的功能。

(5)严格来讲,信号与槽的参数个数与类型要一致,至少信号参数不能少于槽的参数,否则会出错。

(6)使用信号与槽的类,必须在类的定义中加入宏Q_OBJECT。

(7)信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。

(8)为了提高开发效率,Qt 的各个控件类都提供了一些常用的信号函数和槽函数。

(9)实际开发中,可以使用 Qt 提供的信号函数和槽函数,也可以根据需要自定义信号函数和槽函数。

简易计算器的实现

首先在widget.ui中进入设计界面,拖动组件并进行图形化构建

 

 选择组件右键转到槽,之后进入widget.cpp页面中设计槽(发生的事件)

 代码展示

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStack>
#include <String>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_b1_clicked();

    void on_b2_clicked();

    void on_deng_clicked();

    void on_jia_clicked();

    void on_jian_clicked();

    void on_cheng_clicked();

    void on_pushButton_7_clicked();

    void on_b4_clicked();

    void on_b5_clicked();

    void on_b6_clicked();

    void on_b6_2_clicked();

    void on_b7_clicked();

    void on_b8_clicked();

    void on_b0_clicked();

    void on_dian_clicked();

    void on_yu_clicked();

    void on_pushButton_20_clicked();

    void on_b3_clicked();

    void on_AC_clicked();

    void on_pushButton_21_clicked();

private:
    Ui::Widget *ui;
    QString expression;
    int Priority(char ch);
};

#endif // WIDGET_H

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->deng->setStyleSheet("background:blue");
}

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

void Widget::on_b1_clicked()
{
    expression += "1";
    ui->lineEdit->setText(expression);
}

void Widget::on_b2_clicked()
{
    expression += "2";
    ui->lineEdit->setText(expression);
}

void Widget::on_deng_clicked()
{
    QStack<int> s_num,s_opt;
    char opt[128]={0};
    int i=0,tmp=0,num1,num2;
    //把QString转换成char*
    QByteArray ba;
    ba.append(expression);//把QString转化成QByteArry
    strcpy(opt,ba.data());//data可以把QByteArry转换成const char*

    while(opt[i]!='\0'||s_opt.empty()!=true)
    {
        if(opt[i]>='0'&&opt[i]<='9')
        {
           tmp = tmp*10+opt[i]-'0';
           i++;
           if(opt[i]<'0'||opt[i]>'9')
           {
               s_num.push(tmp);
               tmp=0;
           }
        }
        else{
            if(s_opt.empty()==true||Priority(opt[i]>Priority(s_opt.top()))||(s_opt.top()=='('&&opt[i]!=')'))
            {
                s_opt.push(opt[i]);
                i++;
                continue;
            }
            if(s_opt.top()=='('&&opt[i]==')')
            {
                    s_opt.pop();
                    i++;
                    continue;
            }
            if(Priority(opt[i])<=Priority(s_opt.top())||(opt[i]==')'&&s_opt.top()!='(')||(opt[i]=='\0'&&s_opt.empty()!=true)){
                    char ch = s_opt.top();
                    s_opt.pop();
                    switch(ch)
                {
                    case '+':
                        num1=s_num.top();
                        s_num.pop();
                        num2=s_num.top();
                        s_num.pop();
                        s_num.push(num1+num2);
                        break;
                    case '-':
                        num1=s_num.top();
                        s_num.pop();
                        num2=s_num.top();
                        s_num.pop();
                        s_num.push(num2-num1);
                        break;
                    case '*':
                        num1=s_num.top();
                        s_num.pop();
                        num2=s_num.top();
                        s_num.pop();
                        s_num.push(num1*num2);
                        break;
                    case '/':
                        num1=s_num.top();
                        s_num.pop();
                        num2=s_num.top();
                        s_num.pop();
                        s_num.push(num2/num1);
                        break;
                }

            }
        }
    }
    ui->lineEdit->setText(QString::number(s_num.top()));
    expression.clear();
}

int Widget::Priority(char ch)
{
     switch(ch)
       {
           case '(':
               return 3;
           case '*':
           case '/':
               return 2;
            case '+':
            case '-':
               return 1;
            default:
               return 0;
        }
}

void Widget::on_jia_clicked()
{
    expression += "+";
    ui->lineEdit->setText(expression);
}

void Widget::on_jian_clicked()
{
    expression += "-";
    ui->lineEdit->setText(expression);
}

void Widget::on_cheng_clicked()
{
    expression += "*";
    ui->lineEdit->setText(expression);
}

void Widget::on_pushButton_7_clicked()
{
    expression += "/";
    ui->lineEdit->setText(expression);
}

void Widget::on_b4_clicked()
{
    expression += "4";
    ui->lineEdit->setText(expression);
}

void Widget::on_b5_clicked()
{
    expression += "5";
    ui->lineEdit->setText(expression);
}

void Widget::on_b6_clicked()
{
    expression += "6";
    ui->lineEdit->setText(expression);
}

void Widget::on_b6_2_clicked()
{
    expression += "7";
    ui->lineEdit->setText(expression);
}

void Widget::on_b7_clicked()
{
    expression += "8";
    ui->lineEdit->setText(expression);
}

void Widget::on_b8_clicked()
{
    expression += "9";
    ui->lineEdit->setText(expression);
}

void Widget::on_b0_clicked()
{
    expression += "0";
    ui->lineEdit->setText(expression);
}


void Widget::on_dian_clicked()
{
    expression += ")";
    ui->lineEdit->setText(expression);
}

void Widget::on_yu_clicked()
{
    expression += "(";
    ui->lineEdit->setText(expression);
}

void Widget::on_pushButton_20_clicked()
{
    expression += "+/-";
    ui->lineEdit->setText(expression);
}

void Widget::on_b3_clicked()
{
    expression += "3";
    ui->lineEdit->setText(expression);
}

void Widget::on_AC_clicked()
{
    expression.clear();
    ui->lineEdit->clear();
}

void Widget::on_pushButton_21_clicked()
{
    expression.chop(1);
    ui->lineEdit->setText(expression);
}

widget.ui

 运行展示

 遇到的问题

 

J:\QT\QTdaima\computer\widget.cpp:32: error: 'Qstack' was not declared in this scope
     Qstack<int> s_num,s_opt;
     ^

 原因:头文件引用错误和字母大小写未注意

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值