Signal and slot problem



  • i am trying to connect my signals and slots but it's not working codes are below

    void gpio::ISR()
    {
        gpio GPIO;
        if(gpio::isHIGH())
        {
            qDebug()<<"RISING Interrupt called";
            GPIO.emit_RisingSignal();
        }
    
        else if(gpio::isLOW())
        {
    
            qDebug() <<"FALLING edge";
            GPIO.emit_FallingSignal();
        }
    }
    
    void gpio::emit_RisingSignal()
    {
        qDebug()<<"In Rising Function.";
        emit RisingEdge();
    }
    
    void gpio::emit_FallingSignal()
    {
        qDebug()<<"In Falling Function";
        emit FallingEdge();
    }
    

    and in Header file

    #include <QObject>
    class gpio : public QObject
    {
        Q_OBJECT
    public:
        gpio();
        void static Initialize();
        void static ISR();
        bool static isHIGH();
        bool static isLOW();
        void emit_RisingSignal();
        void emit_FallingSignal();
    private:
    
        static const int POWER=21;
        static const int BUTTON=20;
    signals:
        void RisingEdge(void);
        void FallingEdge(void);
    
    };
    

    And in MainWindow.cpp

    gpio* GPIO=new gpio();
    connect(GPIO,SIGNAL(RisingEdge()),this,SLOT(inserted()));
    connect(GPIO,SIGNAL(FallingEdge()),this,SLOT(Removed()));
    
    void MainWindow::inserted()
    {
        qDebug()<<"Inserted...";
    }
    
    void MainWindow::Removed()
    {
        qDebug()<<"Removed...";
    }
    

    and in MainWindow.h

    public slots:
    void inserted();
    void Removed();
    

    When i Run this program i Get
    RISING Interrupt called
    In Rising Function.
    FALLING edge
    In Falling Function

    but it should be
    RISING Interrupt called
    In Rising Function.
    Inserted....
    FALLING edge
    In Falling Function
    Removed...

    So clearly the slots are not being called i can't figure out the problem and Help is badly needed.


  • Qt Champions 2016

    @azravian said:
    hi
    first thing to do is to use

    qDebug() <<"con1" << connect(xxx

    for all your connect and check they all return true;



  • @mrjj

    qDebug()<<"Connection Rising edge: "<<connect(GPIO,SIGNAL(RisingEdge()),this,SLOT(inserted()));
        qDebug()<<"Connection falling edge:"<<connect(GPIO,SIGNAL(FallingEdge()),this,SLOT(Removed()));
    

    gives the output

    Connection Rising edge: true
    Connection falling edge: true


  • Qt Champions 2016

    @azravian said:
    ok super so they accept the connect.

    your error is here

    void gpio::ISR()
    {
    gpio GPIO; <<<<<<<<<<<<<< that is not the one u connect !?

    That is not the
    gpio* GPIO=new gpio();
    one :)

    Update:
    So when you do
    GPIO.emit_FallingSignal();
    with your local copy, no signal is sent to mainwin as
    its an other instance than the one you new in main.



  • @mrjj that's seems to be a problem but if i change my ISR()

    void gpio::ISR()
    {
        gpio* GPIO=new gpio;
        if(gpio::isHIGH())
        {
            qDebug()<<"RISING Interrupt called";
            GPIO->emit_RisingSignal();
        }
    
        else if(gpio::isLOW())
        {
    
            qDebug() <<"FALLING edge";
            GPIO->emit_FallingSignal();
        }
    }
    i have the same problem, it didn't solve the problem/
    

  • Qt Champions 2016

    but why are u creating a new Object???
    Use the one in/from main.

    That is the one you have connect to mains slots so making a new one
    in that function will not send any signals to main as you do not connect it
    like the other one.

    So just newing the local copy instead, will not make any difference :)


  • Qt Champions 2016

    @mrjj

    wait, i just saw
    you create a gpio INSIDE gpio ????

    why?


  • Qt Champions 2016

    I would expect

    void gpio::ISR()
    {

    if(gpio::isHIGH())
    {
        qDebug()<<"RISING Interrupt called";
        emit_RisingSignal();
    }
    

    No local object of same type! ?



  • @mrjj Sir, ISR() is a static function. So to access other functions of the class i need to create an object :) thats why i have defined two other function emit_RisingEdge() and emit_FallingEdge() so i can emit my signals independent of any object.


  • Qt Champions 2016

    Ok, if u create a instance for use with signals, then its fine.
    You just need to connect this new object to the slots again.



  • @mrjj thanks but i'm pretty much beginner with signals and slots,where do i need to change my code


  • Qt Champions 2016

    @azravian
    Hi,
    void gpio::ISR()
    {
    gpio* GPIO=new gpio;
    // here u need to connect again
    // since its not pr type, but pr instance
    // so the connect u made in main, are not on GPIO here



  • @mrjj thank you it worked thank you so much Sir :)


  • Qt Champions 2016

    @azravian
    Super, np :)
    sorry I missed ur static function. The scroll area is so tiny .)



  • @mrjj
    Oh it's Ok sir, thanks Again for your input and help :) I've surely learned a lot


  • Lifetime Qt Champion

    Hi,

    Just one thing, you have now a memory leak.

    But in any case, I must say I don't see any reason for making all these methods static.


  • Qt Champions 2016

    @SGaist
    Thank champ. In the static heat, i completely missed that.

    @azravian
    You should have a
    delete GPIO in the end of the function or even better
    just go back to using the stack again. (so it cleans it self)
    void gpio::ISR()
    {
    gpio GPIO;



  • @mrjj @SGaist
    Yes i noticed it later and have deleted it. thanks again sir



  • @SGaist thank you for it :) and the point od making these methods statics is that i am using wiringPi library which need a function as a parameter so i need make it static.


  • Moderators

    @azravian In this case you could add a public static method to get the pointer to the gpio instance (basically you create a singleton):

    class gpio : public QObject
    {
        Q_OBJECT
    public:
        gpio(): instancePtr(nullptr) {}
        static gpio* instance()
        {
            if (!instancePtr) instancePtr = new gpio();
            return instancePtr;
        }
    private:
        gpio* instancePtr;
    

    You can use this method in main to setup the connection and in static methods in gpio to get the pointer to the instance. Don't forget to delete the instance later.


  • Lifetime Qt Champion

    @jsulm you forgot to also make instancePtr static. However, I don't think the singleton pattern should be applied here.


  • Moderators

    @SGaist Yes, I forgot, thanks for pointing :-)



  • @mrjj @SGaist
    Now it's all working now but i cannot use ui memeber like label, lineEdit etc. For example

    void MainWindow::inserted()
    {
        qDebug()<<"Inserted...";
        ui->label->setText("Inserted");
    }
    

    i do get "Inserted..." but the label does not change Text :(


  • Lifetime Qt Champion

    Silly question but are you user the label is visible ? Do you have something on it before you call inserted ?



  • @SGaist yes for instance it has the default text "textLabel" and that's visible on GUI


  • Lifetime Qt Champion

    Then do you have something else that modifies that label ?

    Things would be a bit easier if there was a possibility to see your code.



  • @SGaist
    Sure Sir, it's the same code except i added just one line

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "gpio.h"
    #include <QDebug>
    
    bool firstTime=true;
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        if(firstTime)
        {
            gpio::Initialize();
            firstTime=false;
        }
        gpio* GPIO=new gpio;
        connect(GPIO,SIGNAL(RisingEdge()),this,SLOT(inserted()));
        connect(GPIO,SIGNAL(FallingEdge()),this,SLOT(Removed()));
        delete GPIO;
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    void MainWindow::inserted()
    {
        qDebug()<<"Inserted...";
        ui->label->setText("Inserted");
    }
    
    void MainWindow::Removed()
    {
        ui->label->setText("Inserted");
        qDebug()<<"Removed...";
    }
    
    
    

  • Lifetime Qt Champion

    If I may, you really should first cleanup your gpio class. It looks wrongly implemented and is wrongly used.

    Make it a normal object i.e. don't use any static in it and don't make it a singleton. Once you have that sorted, it will be easier to integrate it in your GUI.



  • @SGaist
    if i don't use ISR() and Initialize() as static i get error with wiringPiISR()
    as
    wiringPiISR (BUTTON, INT_EDGE_BOTH,&ISR);
    it gives an error
    error: cannot convert 'void (gpio::)()' to 'void ()()' for argument '3' to 'int wiringPiISR(int, int, void (*)())'
    wiringPiISR (BUTTON, INT_EDGE_BOTH,&ISR);
    ^


  • Lifetime Qt Champion

    Ok, and there's no way to pass any parameter so here is an implementation example using a singleton:
    WARNING : not tested on a Pi.

    rpigpio.h

    #ifndef RPIGPIO_H
    #define RPIGPIO_H
    
    #include <QObject>
    
    class RpiGPIO : public QObject
    {
        Q_OBJECT
    
    public:
        static RpiGPIO *instance();
        static void destroy();
    
        static void initialize(int buttonNumber);
    
    signals:
        void edgeRaised();
        void edgeFalled();
    
    private:
        RpiGPIO();
    
        static void raisingEdgeCallback();
        static void fallingEdgeCallback();
    
        void onRaisingEdge();
        void onFallingEdge();
    
    private:
        static RpiGPIO *_gpio;
    };
    
    #endif
    

    rpigpio.cpp

    
    #include "gpio.h"
    
    RpiGPIO *RpiGPIO::_gpio = nullptr;
    
    RpiGPIO::RpiGPIO()
       : QObject(nullptr)
    {}
    
    RpiGPIO *RpiGPIO::instance()
    {
        if (!_gpio) {
            _gpio = new RpiGPIO;
        }
    
        return _gpio;
    }
    
    void RpiGPIO::destroy()
    {
        delete _gpio;
    }
    
    void RpiGPIO::initialize(int buttonNumber)
    {
        wiringPiISR(buttonNumber, INT_EDGE_RAISING, RpiGPIO::raisingEdgeCallback);
        wiringPiISR(buttonNumber, INT_EDGE_FALLING, RpiGPIO::fallingEdgeCallback);
    }
    
    void RpiGPIO::raisingEdgeCallback()
    {
        RpiGPIO::instance()->onRaisingEdge();
    }
    
    void RpiGPIO::fallingEdgeCallback()
    {
        RpiGPIO::instance()->onFallingEdge();
    }
    
    void RpiGPIO::onRaisingEdge()
    {
        emit edgeRaised();
    }
    
    void RpiGPIO::onFallingEdge()
    {
        emit edgeFalled();
    }
    

    Then you can do in your MainWindow:

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        RpiGPIO::initialize(numberOfTheButtonYouWantToMonitor);
        connect(RpiGPIO::instance(), &RpiGPIO::edgeRaised, [](){ qDebug("raising");});
        connect(RpiGPIO::instance(), &RpiGPIO::edgeFalled, [](){ qDebug("falling");});
    }
    
    MainWindow::~MainWindow()
    {
        RpiGPIO::destroy();
    }
    

    If you want to be even cleaner, move the calls to initialize and destroy in your main.cpp:

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        RpiGPIO::initialize(buttonYouWantToMonitor);
        MainWindow mw;
        mw.show();
        int ret = app.exec();
        RpiGPIO::destroy();
        return ret;
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.