Passing Data to a Slot



  • Let’s say that I have a method with a connection to a slot:

    myMethod()
    {
    int x = 5;

    connect(TheButton, SIGNAL(clicked(), this, SLOT(myHandler())); <— SIGNAL contains clicked() and SLOT contains myHandler(), but the editor eats it.
    }

    myHandler()
    {
    // Do something
    }

    How do I pass x to the slot? In the real problem, the value of x wouldn’t be fixed as in this example. Please don’t ask me why I need to pass the data. I promise, I need to. Thanks.



  • You specify what you pass when you emit the signal, not when you connect.

    You can:
    @
    emit mySignal(x);@

    this is in case you have a slot that receives an int parameter

    In the case of a button, the clicked() signal doesn't have any parameter, so you can either use std::bind, or the simpler but not as elegant approach would be to connect the button signal to a slot that accepts no parameter, and in that slot emit a signal with a parameter that is connected to a slot with a parameter.



  • Thanks, but how would this look in the example I gave?



  • @// in the header
    signals:
    void mySignal(int value);
    public slots:
    void myHandler(int value) {
    qDebug() << "value is" << value;
    }

    // in the implementation
    ...
    connect(this, SIGNAL(mySignal(int)), this, SLOT(myHandler(int)));
    ...
    emit mySignal(7);
    emit mySignal(someIdentifier);
    emit mySignal(someFunction());@



  • So I used both this connect() and also the one I had which connects the clicked() event? Will it pass the number when and only when the clicked() event occurs? When the button is clicked, it has to pass whatever number applies at that moment.



  • No, clicked doesn't emit a value, it emits void, you have to connect clicked to another slot that emits the value to the slot that accepts the value

    @// in the header
    signals:
    void mySignal(int value);

    public slots:
    void myHandler(int value) { // this method will receive the value
    qDebug() << "value is" << value;
    }

    void buttonHandler(){ // the button will execute this method to pass a value
        i = 10;
        emit myHandler(i);
    }
    

    private:
    int i; // this is the value

    // in the constructor
    QPushButton *button = new QPushButton("emit", this);

    connect(button, SIGNAL(clicked()), this, SLOT(buttonHandler()));
    connect(this, SIGNAL(mySignal(int)), this, SLOT(myHandler(int)));@

    So when you press the button, it will emit the clicked() signal, which will trigger the buttonHandler() slot, which will emit the value to the myHandler slot, which will output it.

    If you have a signal that actually emits a value you don't have to do that, but QPushButton's clicked() signal doesn't have any parameters, so you either have to bind a value, to subclass and overload the clicked() signal to emit a value, or use an additional stage to emit the value, as in the example above.



  • When the clicked() signal triggers buttonHandler(), how does buttonHandler() get the data (x in my example) so that it can emit the value to myHandler()?



  • You can also take a look at QSignalMapper. It allows you to bind signals to slots through a mapping.

    "QSignalMapper":http://qt-project.org/doc/qt-4.8/qsignalmapper.html#details



  • The data is the i member of the class this all happens. This is just an example, in an actual real world scenario you will pass the value from one object to another.

    For example you may have a user interface with a line edit and a button, and you want to send the content of the line edit to some other class when you click the button.

    The button itself cannot send the value, it can only emit a void signal(void), which you can connect to an accessor method of the user interface, which will be connected to the object you want to send the content of the line edit. So you have it like that:

    UI -> button is clicked -> accessor method is ativated, emits a signal that actually passes a value with the value of the line edit -> the signal is connected to the object you want to send the data from the UI

    ui button -> ui slot -> emit signal with value from the ui -> another object receives the value from the ui



  • Thanks, guys, but I guess it's time to fall back on global variables.



  • Globals are not necessarily a solution, while using them wisely is not problematic, there are many ways to misuse them.

    This is NOT the case to use globals, using globals for such trivial stuff is BAD PROGRAMMING PRACTICE!!!

    I still fail to see what is your problem with signals and slots. Let me put a more practical example - as I mentioned a UI that passes a UI element's value to another object:

    Upon pressing the "Send value" button, the content of the line edit will be send to MyClass, which will output it.

    The "Send value" button triggers a slot inside of MyWidget that emits another signal with the content of the line edit to the MyClass instance.

    MyWidget.h
    @class MyWidget : public QWidget
    {
    Q_OBJECT
    public:
    explicit MyWidget(QWidget *parent = 0);

    signals:
    void redirectData(QString data);

    public slots:
    void sendData(){emit redirectData(edit->text());}

    private:
    QPushButton *button;
    QLineEdit *edit;
    MyClass *myClass; // the object to receive and output the data
    };@

    MyWidget.cpp
    @MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
    {
    button = new QPushButton("Send value", this);
    edit = new QLineEdit(this);
    myClass = new MyClass(this);
    QHBoxLayout *layout = new QHBoxLayout(this);
    layout->addWidget(button);
    layout->addWidget(edit);

    connect(button, SIGNAL(clicked()), this, SLOT(sendData()));
    connect(this, SIGNAL(redirectData(QString)), myClass, SLOT(outputData(QString)));
    

    }@

    MyClass.h
    @class MyClass : public QObject
    {
    Q_OBJECT
    public:
    explicit MyClass(QObject *parent = 0) : QObject(parent) {}

    public slots:
    void outputData(QString data){
    qDebug() << data;
    }
    };
    @

    Pressing the button triggers the sendData slot, which emits the redirectData signal with the content of the line edit, which is connected to the MyClass instance, which outputs the value.



  • Hello,

    I red all of this subject , I understood some of the informations and I realize that I'm actually in the same case that Brandon.
    I would like to pass a QLineEdit in a QString in order to add it in a QListWidget after. But I can't recup my QLineEdit with a button validation because I have ( I suppose ) a problem with public slots and signals.

    This is my code :

    add_window.h

    #ifndef ADD_WINDOW_H
    #define ADD_WINDOW_H
    
    #include <QtGui>
    #include <QtWidgets>
    #include <QString>
    #include <QMessageBox>
    #include <iostream>
    #include <cstdlib>
    
    class Add_window : public QWidget
    {
        Q_OBJECT
    
      public:
        Add_window();
    
      public slots:
        void SendData(QString contenu);
    
      private:
        QLineEdit *URL;
        QPushButton *validation;
        QPushButton *annulation;
    
    
    };
    
    #endif // ADD_WINDOW_H
    

    add_window.cpp

    #include "add_window.h"
    
    
    
    
    Add_window::Add_window() : QWidget()
    {
    
    
        QLineEdit *URL = new QLineEdit;
        QString contenu = URL->text();
        QPushButton *validation = new QPushButton(tr("OK"));
        connect(validation, SIGNAL(clicked()), this, SLOT(SendData(QString contenu)));
        QPushButton *annulation = new QPushButton(tr("Annuler"));
        connect(annulation, SIGNAL(clicked()), this, SLOT(close()));
    
    
        QHBoxLayout *HLayout = new QHBoxLayout;
    
        URL->setText("Entrer une URL");
        HLayout->addWidget(URL);
        HLayout->addWidget(validation);
        HLayout->addWidget(annulation);
        setLayout(HLayout);
    
    }
    
    void Add_window::SendData(QString contenu)
    {
        //Récupération de l'URL
    
        //QString contenu = URL->text();  If i try to recup the value here , my program crashes when I click on the validation button
        QMessageBox::information(this, "URL", QString("phrase") + contenu);
        //QMessageBox::information(this, "URL", "test");
    }
    

    So I don't know where I have to recup my QString if it has to be after the new QLineEdit or in the "void Add_window::SendData()"...


  • Qt Champions 2016

    Hi and welcome
    There are some issues with the code I like to talk about
    1): there are 2 URL
    private:
    QLineEdit *URL;
    but you say
    QLineEdit *URL = new QLineEdit; // this makes a local URL. not the one from private
    Im wonder if u mean
    URL = new QLineEdit; // allocate teh private one

    2:)
    connect(validation, SIGNAL(clicked()), this, SLOT(SendData(QString contenu)));
    You don't pass actual parameters in connect statement. its for setup only.
    Also, the button has clicked() and it has no parameters. so you cant
    really hook up signal click with your slot :SendData(QString contenu)
    as its missing the QString .

    3:)
    I guess u crash in SendData
    QString contenu = URL->text();// If i try to recup the value here
    As you are using the private URL which is not NEWed.

    so if you
    make
    void Add_window::SendData(QString contenu)
    to
    void Add_window::SendData()

    and
    connect(validation, SIGNAL(clicked()), this, SLOT(SendData(QString contenu)));
    to
    connect(validation, SIGNAL(clicked()), this, SLOT(SendData()));

    and "new" the private URL then it should work.
    in
    void Add_window::SendData()
    {
    //Récupération de l'URL
    QString contenu = URL->text();


Log in to reply
 

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