带参的信号、lamda表达式及坐标系统

带参的信号、lamda表达式及坐标系统

一、带参的信号

1. 自定义信号(这个信号不像标准信号是一个宏,而是一个自定义信号函数,注意是信号函数不是信号处理函数,信号处理函数是槽函数)

  • 信号必须由signals关键字声明
  • 信号没有返回值但是可以有参数
  • 信号就是函数的声明无需实现
  • 使用的时候需要加emit + 信号函数的方式
  • 信号可以重载

2. Qt5重载带参信号的使用

**我们上面说过,自定义信号就是自定义一个信号函数,只有声明没有实现**,所以也可以按照函数指针的方式进行区分,不过和函数指针的区别是它要加上信号所在类名::信号函数

那么看下面这种情况:

signals:
    void Mysignal();
    void Mysignal(int,QString);

	void dealsub();
    void dealsold(int,QString);
    connect(&w,&SubWidget::Mysignal,this,&MainWidget::dealsub);
    connect(&w,&SubWidget::Mysignal,this,&MainWidget::dealsold);

	void MainWidget::dealsold(int num,QString arg)
	{
    	qDebug()<<num<<" "<<arg.toUtf8().data();
	}
	void MainWidget::dealsub()
	{
    	w.hide();
    	this->show();
	}

我们重载了Mysignal()信号,在进行connect关联槽函数时编译就会出错,因为编译器无法区分SubWidget::Mysignal信号是带参数的还是不带参数的,所以应进行区分。

方法所在类名::信号函数一起构成函数指针

void (SubWidget::*sub)() = &SubWidget::Mysignal;
connect(&w,sub,this,&MainWidget::dealsub);

void (SubWidget::*subsignal)(int,QString) = &SubWidget::Mysignal;
connect(&w,subsignal,this,&MainWidget::dealsold);

3.QT中的输出
qDebug:函数

#include <QDebug>//头文件
qDebug(const char *message, ...)
  • 注意第一个q是小写
  • 注意还有一个()
  • 自动换行
  • 和cout用法基本一样

qDebug()<<num<<" "<<arg.toUtf8().data();

4. QString转char*

//字节数组
QByteArray QString::toUtf8() const
//C字符串
char *QByteArray::data()

//arg.toUtf8() -> 字节数组
//arg.toUtf8().data()->C字符串
qDebug()<<num<<" "<<arg.toUtf8().data();

5. Qt4信号连接

  • Qt4槽函数必须有slots声明
  • SIGNAL和SLOT宏 是将函数名字转换为字符串
  • 采用Qt5的函数指针的方式使用会参与类型安全检查,而Qt4宏的方式不参与安全检查,只有到运行时才报错
signals:
    void Mysignal();
    void Mysignal(int,QString);
    
public slots:
    void dealsub();
    void dealsold(int,QString);
connect(&w,SIGNAL(Mysignal()),this,SLOT(dealsub()));
connect(&w,SIGNAL(Mysignal(int,QString)),this,SLOT(dealsold(int,QString)));

void MainWidget::dealsold(int num,QString arg)
{
    qDebug()<<num<<" "<<arg.toUtf8().data();
}
void MainWidget::dealsub()
{
    w.hide();
    this->show();
}

使用Qt4宏的方式也可以实现区分重载信号,方便使用,但是一定要注意Qt4宏的方式的缺陷,所以一般采用Qt5的方式,虽然麻烦但是安全

二、lamda表达式

C++11新增加加了lamda表达式,所以也可以用lamda表达式配合Qt信号一起使用!

使用的方式:在项目文件(.pro)中加入CONFIG += c++11

QPushButton* b4 = new QPushButton(this);
    b4->setText("i am lambda");
    b4->move(1,200);
//this可写可不写
connect(b4,&QPushButton::clicked,[](bool check)
    {
       qDebug()<<"i am lambda";
       qDebug()<<check;
    });
  • 注意lambda的捕获列表既可以以值方式捕获,也可以以引用的方式进行捕获,但是 在信号这里最好用值的方式进行捕获

假设上面的代码以引用的方式捕获b4,然后在函数体内对b4进行修改

QPushButton* b4 = new QPushButton(this);
    b4->setText("i am lambda");
    b4->move(1,200);
//this可写可不写
connect(b4,&QPushButton::clicked,[&b4](bool check)
    {
       qDebug()<<"i am lambda";
       qDebug()<<check;
       b4->move(2,200);
    });

程序就会 出错,因为connect正在使用b4,而函数体内的b4刚好是引用方式捕获的,也就是一个别名,内部正在修改,两者就会矛盾,就会导致程序崩溃

  • 注意信号的发出者
	b1.setParent(this);
    b1.setText("close");
    b1.move(10,10);
connect(&b1,&QPushButton::pressed,this,&MainWidget::close);

上面这个代码的功能是当按下b1按钮时,主窗口关闭,你们可能认为信号是b1按钮发送的,其实不是,信号是信号拥有者发送的,而当按下b1按钮时只是触发了槽函数,由槽函数来进行发送信号

三、坐标系统

1. move函数

移动按钮是使用move函数,而移动窗口也是使用move函数,因为move函数是继承与QWidgets,而QWidgets基本上是所有控件的基类,所以窗口也可以用move移动

2.坐标系统

  • 对于主窗口来说:坐标系统是相对于屏幕而言,移动的起点是相对于屏幕的左上角, x:往右递增,y往下增长
  • 对于子窗口来说:坐标系统就是相对于主窗口而言的,移动的起点是主窗口的空白区域,不包括边框
#include "mywidget.h"

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
{
    move(100,100);
    
    QPushButton* b1 = new QPushButton(this);
    b1->setText("i am move b1");
    b1->move(99,99);
    b1->resize(140,140);

    QPushButton* b2 = new QPushButton(b1);
    b2->setText("i am move b2");
    b2->move(0,0);
    b2->resize(30,30);
}

MyWidget::~MyWidget()
{

}

发布了158 篇原创文章 · 获赞 117 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/wolfGuiDao/article/details/105476269