添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

信号槽失效的原因

用Qt进行信号与信号槽连接后,会出现信号槽不响应信号的情况,原因可能是以下的情况:

1、 类没有声明Q_OBJECT;
2、 信号槽没有定义为pubic/protected/private slots;
3、事件被子控件过滤掉了。比如QListWidget,当QListWidgetItem已经处理keypress事件后,QListWidget就不能响应itemDoubleClicked事件了。
4、信号槽的参数是自定义的,这时需要用qRegisterMetaType注册一下这种类型。具体操作可搜索 qRegisterMetaType的使用。

信号槽的两种关联方式

QPushButton *btn = new QPushButton;
    // 方式一:老式写法
    connect(btn, SIGNAL(clicked()), this, SLOT(close()));
    // 方式二:Qt5后新写法
    connect(btn, &QPushButton::clicked, this, &MainWindow::close);
    // 方式三:lambda表达式
    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即可。
//在myButton.h中新建一个protected函数
protected:
    void test(){
        qDebug() << "myButton";
//在mainwidget.cpp中创建对象并调用,
 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

解决办法:

  1. 若test()函数类型为public则不报错。
  2. 使用老式的连接方式:
 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()` 函数就会被执行,从而实现了多窗口之间的信号传递。