Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Signal is emitting, connection returns true, slot not triggering



  • This is the second way I have rearranged this, and it is doing the same thing, so now I seek help. There are no errors being thrown, the slot just never does anything.
    There are two other connections that are working between the same two cpps, and I decided to add this third one that the main window triggers, to the main window.

    on_line_edit_return_pressed(), is printing hol_num and that is where it ends. ReadyHollander emits and HolPub never does anything. What am I doing wrong?

    mainwindow cpp

    #include "wheelscannerui.h"
    #include "./ui_wheelscannerui.h"
    
    gui_image_node *m_gui_image_node;
    WheelScannerUI::WheelScannerUI(QWidget *parent)
        : QMainWindow(parent),
        ui(new Ui::WheelScannerUI)
    
    {
        ui->setupUi(this);
        connect(m_gui_image_node, &gui_image_node::ReadyImage, this, &WheelScannerUI::updateWheelImage);
        connect(m_gui_image_node, &gui_image_node::OpenHollander, this, &WheelScannerUI::Open_No_ID);
        connect(this, &WheelScannerUI::ReadyHollander, m_gui_image_node, &gui_image_node::HolPub);
        qDebug() << connect(this, &WheelScannerUI::ReadyHollander, m_gui_image_node, &gui_image_node::HolPub);
        ui->lineEdit->setVisible(false);
        QMainWindow::showFullScreen();
    }
    
    WheelScannerUI::~WheelScannerUI()
    {
        delete ui;
    }
    
    void WheelScannerUI::Open_No_ID(QString qsteve)
    {
        ui->lineEdit->setVisible(true);
    }
    
    void WheelScannerUI::on_lineEdit_returnPressed()
    {
        QString hol_num = ui->lineEdit->text();
        Q_EMIT ReadyHollander(hol_num);
        ui->lineEdit->setVisible(false);
        ui->lineEdit->clear();
        qDebug() << hol_num;
    }
    

    main windows .h

    #ifndef WHEELSCANNERUI_H
    #define WHEELSCANNERUI_H
    
    #include <QMainWindow>
    #include <QtSql>
    #include <QSqlQuery>
    #include <QSqlDatabase>
    #include <QSqlQueryModel>
    
    #include "gui_image_node.h"
    #include <QPixmap>
    
    #include <ros/ros.h>
    #include <std_msgs/String.h>
    #include <std_msgs/Int64.h>
    #include <sensor_msgs/image_encodings.h>
    #include <nodelet/nodelet.h>
    #include <image_transport/image_transport.h>
    #include <cv_bridge/cv_bridge.h>
    #include <opencv2/highgui/highgui.hpp>
    #include <pluginlib/class_list_macros.h>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
    #include <iostream>
    extern gui_image_node *m_gui_image_node;
    QT_BEGIN_NAMESPACE
    namespace Ui { class WheelScannerUI; }
    QT_END_NAMESPACE
    
    class WheelScannerUI : public QMainWindow
    {
        Q_OBJECT
    
    public:
        WheelScannerUI(QWidget *parent = nullptr);
        ~WheelScannerUI();
        WheelScannerUI *m_WheelScannerUI;
        void connectionClose()
        {
            db.close();
            db.removeDatabase(QSqlDatabase::defaultConnection);
        }
        bool connectionOpen()
        {
            db = QSqlDatabase::addDatabase("QSQLITE");
            db.setDatabaseName("~/wheels.db");
    
            if(!db.open())
            {
                qDebug()<<("Database failed to open");
                return false;
            }
            else{
                qDebug()<<("database connected");
                return true;
            }
        }
    public slots:
        Q_SLOT void Open_No_ID(QString qsteve);
    
        Q_SLOT void open_db_table(); //trigger with a ros callback?
    
    signals:
        Q_SIGNAL void ReadyHollander(QString);
    private slots:
    
        void on_lineEdit_returnPressed();
    
        void on_Mode_Button_clicked();
    
    private:
        Ui::WheelScannerUI *ui;
        QSqlDatabase db;
    
    
    
    };
    #endif // WHEELSCANNERUI_H
    

    node cpp

    
    #include "gui_image_node.h"
    gui_image_node::gui_image_node()
    {
    
    }
    
    bool gui_image_node::init(int argc, char** argv)
    {
        m_pThread = new QThread();
    
        this->moveToThread(m_pThread);
     
        connect(m_pThread, &QThread::started, this, &gui_image_node::run);
    
        ros::init(argc, argv, "wheels_gui_image");
    
        if ( ! ros::master::check() )
        {
            return false;
        }
    
        ros::start();
        ros::Time::init();
        ros::NodeHandle nh;
    
        hollander_pub = nh.advertise<std_msgs::String>("/hollander_chat", 1);
        hol_trigger = nh.subscribe("awaiting_hollander", 1, &gui_image_node::Hollander_Screen_trigger_callback, this);
    
        m_pThread->start();
        return true;
    }
    
    
    void gui_image_node::Hollander_Screen_trigger_callback(const std_msgs::String::ConstPtr& msg)
    {
        std::string steve = msg->data; 
        QString qsteve = QString::fromStdString(steve);
        Q_EMIT OpenHollander(qsteve);
    }
    void gui_image_node::HolPub(QString hol_num)
    {
        qDebug() << "received number";
        std::string hol_num_conv = hol_num.toUtf8().constData();
        std_msgs::String msg;
        msg.data = hol_num_conv;
        hollander_pub.publish(msg);
    }
    
    

    nodes .h

    #ifndef GUI_IMAGE_NODE_H
    #define GUI_IMAGE_NODE_H
    
    #include <ros/ros.h>
    #include <nodelet/nodelet.h>
    #include <image_transport/image_transport.h>
    #include <cv_bridge/cv_bridge.h>
    #include <opencv2/highgui/highgui.hpp>
    #include <std_msgs/String.h>
    
    #include <QMainWindow>
    #include <QObject>
    #include <QSharedDataPointer>
    #include <QWidget>
    #include <QThread>
    #include <string>
    #include <QMutex>
    #include <QDebug>
    
    #include <QDialog>
    #include <stdio.h>
    #include <string.h>
    #include <sstream>
    #include <iostream>
    
    class gui_image_node : public QThread
    {
        Q_OBJECT
    public:
        gui_image_node();
        ~gui_image_node();
        bool init(int argc, char** argv);
        void Hollander_Screen_trigger_callback(const std_msgs::String::ConstPtr& msg);
    
    protected:
    public slots:
        Q_SLOT void run();
        Q_SLOT void HolPub(QString hol_num);
    signals:
        Q_SIGNAL void OpenHollander(QString);
    
    private:
        ros::Publisher hollander_pub;
        ros::Subscriber hol_trigger;
        QThread * m_pThread;
    
    };
    
    #endif // GUI_IMAGE_NODE_H
    


  • @IG213 said in Signal is emitting, connection returns true, slot not triggering:

    gui_image_node *m_gui_image_node;

    Why is this in your cpp and not a priv. / pub. member in your header?

    @IG213 said in Signal is emitting, connection returns true, slot not triggering:

    connect(this, &WheelScannerUI::ReadyHollander, m_gui_image_node, &gui_image_node::HolPub);
    qDebug() << connect(this, &WheelScannerUI::ReadyHollander, m_gui_image_node, &gui_image_node::HolPub);

    You can remove the first line, but this has probably nothing to do with your problem :)

    Only the HolPub slot is not working?!



  • @Pl45m4
    The senior engineer made it a global variable a while back, it is created in main.cpp. Could that be the issue? I remember from school that global variables are danger zone.

    And yes, only HolPub doesn't work, I have 4 slots in total in the program, this is the only one not working.



  • I have now changed gui_image_node to be passed through inheritance instead of globally, and the issue still persists.
    EDIT:
    I change on_lineEdit_returnPressed(), so that it opens another function, to make sure slots weren't mixed, no effect.
    Here is the secondary function .

    void WheelScannerUI::on_lineEdit_returnPressed()
    {
        QString hol_num = ui->lineEdit->text();
        //Q_EMIT ReadyHollander(hol_num);
        emithol(hol_num);
        ui->lineEdit->setVisible(false);
        ui->lineEdit->clear();
    
    }
    
    void WheelScannerUI::emithol(QString hol_num)
    {
        qDebug() << hol_num;
        Q_EMIT ReadyHollander(hol_num);
    }
    


  • OK, I solved it.
    connect(this, &WheelScannerUI::ReadyHollander, m_gui_image_node, &gui_image_node::HolPub, Qt::Directconnection);
    I added Qt::Directconnection, since the emit is coming from a different thread than the slot, this allows the cross thread event to be triggered.



  • @IG213
    In general when you use DirectConnection across threads be aware of what @jsulm said here:
    https://forum.qt.io/topic/69618/about-qt-directconnection/2

    If you use direct connection then the slot will be executed in your thread which is not necessarily same thread as the class with the slot. This may work or not depending on what you do in the slot (if you access objects/variables located in another thread your app can crash). In general it is better to use queued connection between threads.


Log in to reply