目录
信号与槽(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;
^
原因:头文件引用错误和字母大小写未注意