QPushButton *btn = new QPushButton;
connect(btn, SIGNAL(clicked()), this, SLOT(close()));
connect(btn, &QPushButton::clicked, this, &MainWindow::close);
connect(btn, &QPushButton::clicked, this, [&]() {
this->close();
});
方式一 老式写法,在编译的时候即使信号或槽不存在也不会报错,但是在执行的时候无效,对于C++这种静态语言来说,这是不友好的,不利于调试;
方式二 Qt5后推荐的写法,如果编译的时候信号或槽不存在是无法编译通过的,相当于编译时检查,不容易出错,还有就是槽的写法可以直接写在public控制域下,不一定非要写在public slots:控制域下;
方式三 采用了lambda表达式的写法,更加方便快捷。
注意事项:
- 方式一的槽函数要写在 public slots: 控制域下
- 方式二在Qt5中是可以传入信号和槽的“函数指针”的,通俗一点就是可以直接将“函数名”作为参数传进去,正是因为这一点,在写“槽”的时候就需要注意到public、protected和private的问题。
在以前的Qt4中,“信号和槽”是通过SIGNAL()和SLOT()的方式来连接的,现在可以使用“函数名”的方式来连接,就需要考虑到“函数名”是否有效 ,
在将“槽”声明为protected和private的时候,在类外是不能直接通过对象来访问到该函数的,即:在类外使用connect并传入“函数名”时,将会编译不通过,此时需要将protected、private更改为public即可。
protected:
void test(){
qDebug() << "myButton";
myButton *btn =new myButton;
connect (rotateSlider,&QSlider::valueChanged ,btn,&myButton::test );
mainwidget.cpp:84:68: error: 'test' is a protected member of 'myButton'
mybutton.h:13:10: note: declared protected here
解决办法:
- 若test()函数类型为public则不报错。
- 使用老式的连接方式:
connect (rotateSlider,SIGNAL (valueChanged(int)),btn,SLOT(test()));
不过要注意test()函数要声明为protected slots:
protected slots:
void test(){
qDebug() << "myButton";
信号槽失效的原因用Qt进行信号与信号槽连接后,会出现信号槽不响应信号的情况,原因可能是以下的情况:1、类没有声明Q_OBJECT;2、信号槽没有定义为pubic/private slots;3、事件被子控件过滤掉了。比如QListWidget,当QListWidgetItem已经处理keypress事件后,QListWidget就不能响应itemDoubleClicked事件了。4、信号槽的参数是自定义的,这时需要用qRegisterMetaType注册一下这种类型。具体操作可搜索 qRegist
这里面,发送了sigJumpu信号后,触发不了槽onTestJump,原因就是我应该把connect写在最前面,如下图:
这样就会触发了,顺序很重要,这种小细节不注意的话。找原因要找死人啊,看似简单,其实很重要。
下面记录下网上一些比较大众的原因:(括号内是我的注解)
1)槽函数未声明为 slots 类型, 信号函数...
最近在开发中遇到一个很奇怪的问题 ,槽函数与信号连接后,在代码执行中发出信号,槽函数始终进不去。一开始认为是connect调用传参不对,打了下返回值是true,而且在输出中也没有相关warnning输出。再一看跨线程信号槽调用,所以猜测跟多线程有关。排查过程中各种换信号、改参数都没有效果,偶然间把接收对象的创建移至主线程,槽函数居然执行成功了。本着有问题看手册的原则,在手册中找到了如下的说明:
大体意识是说:Qobject对象是有线程归属的,或者说其存活在特定线程中。当接收到队列连接的信或 投递的事件,槽
周末天冷,索性把电脑抱到床上上网,这几天看了 dbzhang800 博客关于 Qt 事件循环的几篇 Blog,发现自己对 Qt 的事件循环有不少误解。从来只看到现象,这次借 dbzhang800 的博客,就代码论事,因此了解到一些 Qt 深层的实现,虽然是在 Qt 庞大的构架里只算的是冰山的一角,确让人颇为收益。
从 dbzhang800 的博客中转载两篇关于事件循环的文章,放在
connect(thread_Encoder, SIGNAL(send_current_encoder(long encoder)),
this,SLOT(recive_current_encoder(long encoder)), Qt::DirectConnection);
connect(thread_Encoder, SIGNAL(send_current_encoder(lon
信号槽无法触发的原因,无非就就下面几种:
1.忘记连接信号槽,这种错误十分低级,排查难度一颗星;
2.信号槽中使用了自定义参数(此处应该注意自定义参数是包括数组的,本人在此处吃过一次亏,浪费了半天时间排查),但是没有注册过,应该在开头使用qRegisterMetaType<Mytype>("Mytype");注册,排查难度两颗星;
3.实际槽运行的线程资源被占用,或者是槽所在的对象正在其他的槽响应过程中,这个问题需要带调试排查,排查难度三颗星。
第3点在线程架构设计的时候就需要考虑到这个问题,尽
以上三点是:一般或者网上的总结,现在我多加一点,也可能是一般人不会犯的,但是却让我一脸懵逼了一早上。
就是关联信号槽connect,不是声明了对象就以为没有问题了,一定要在new了对象之后才行。
而且要是多个同类的对象都需要关联同一个槽的话,...
```cpp
connect(sender, SIGNAL(mySignal()), receiver1, SLOT(mySlot()));
connect(sender, SIGNAL(mySignal()), receiver2, SLOT(mySlot()));
这样,当 `sender` 发出 `mySignal()` 信号时,`receiver1` 和 `receiver2` 都会执行 `mySlot()` 槽函数。
2. 使用 `Qt::DirectConnection` 连接方式,将多个槽函数链接为单个槽函数:
```cpp
connect(sender, SIGNAL(mySignal()), receiver, SLOT(myCombinedSlot()), Qt::DirectConnection);
在 `receiver` 类中,定义一个 `myCombinedSlot()` 槽函数,将多个槽函数的逻辑代码组合在一起。当 `sender` 发出 `mySignal()` 信号时,`receiver` 就会执行 `myCombinedSlot()` 槽函数,从而执行多个槽函数的逻辑代码。
在多窗口之间使用信号槽时,需要注意以下几点:
1. 如果信号和槽函数在不同的窗口中,需要使用 `connect()` 函数将它们连接起来。例如:
```cpp
connect(window1, SIGNAL(mySignal()), window2, SLOT(mySlot()));
这样,当 `window1` 中发出 `mySignal()` 信号时,`window2` 中的 `mySlot()` 槽函数会被执行。
2. 如果信号和槽函数在同一个窗口中,只需要在窗口类的头文件中声明信号和槽函数,并使用 `connect()` 函数将它们连接起来。例如:
```cpp
class MyWindow : public QWidget
Q_OBJECT
public:
explicit MyWindow(QWidget *parent = nullptr);
~MyWindow();
signals:
void mySignal();
public slots:
void mySlot();
// 在构造函数中连接信号和槽函数
MyWindow::MyWindow(QWidget *parent) :
QWidget(parent)
connect(this, SIGNAL(mySignal()), this, SLOT(mySlot()));
// 在槽函数中发出信号
void MyWindow::mySlot()
emit mySignal();
这样,在 `MyWindow` 窗口中发出 `mySignal()` 信号时,`mySlot()` 槽函数就会被执行,从而实现了多窗口之间的信号槽传递。