Signal & Slot Problem



  • Hello my friends,

    I want to do something basic. But I can't do it. In my app, there are 2 classes, DropArea and MainWindow. I want to send signal from DropArea class to MainWindow class. There are the codes below. Where is my fault?

    mainwindow.h file,

    ...
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    public slots:
        void moveFile(QString path);
    
    private:
        Ui::MainWindow *ui;
    
        DropArea *dropArea;
    ...
    

    mainwindow.cpp file,

    ...
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        dropArea = new DropArea;
        
    connect(dropArea, SIGNAL(fileDropped(QString)), this, SLOT(moveFile(QString))); **//This is my connect function**
    ...
    

    droparea.h file,

    ...
    class DropArea : public QLabel
    {
        Q_OBJECT
    
    public:
        DropArea(QWidget *parent = 0);
    
    public slots:
        void clear();
    
    signals:
        void changed(const QMimeData *mimeData = 0);
        void fileDropped(QString filePath); **//This is my signal to send**
    
    protected:
        void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
        void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE;
        void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE;
        void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
    ...
    

    droparea.cpp file,

    ...
    void DropArea::dropEvent(QDropEvent *event)
    {
    ...
        emit fileDropped(newPath); **//Emitting signal**
    ...
    }
    ...
    


  • Did you call setAcceptDrops(true) in the DropArea constructor?



  • Yes I would check that your signal is properly emitted first, put a debug message in "void DropArea::dropEvent(QDropEvent *event)" to see if you get there.
    Then put another message in the slot "void moveFile(QString path);" Should see where the problem is.
    Good luck!



  • Another thing that you could do in order to check whats going on, is to verify if the connection was succesfully made. The connect method returns a bool. As i had many times problems with signals and slots, I always check this value, just to be sure. It would be something like this.

    if(!connect(dropArea, SIGNAL(fileDropped(QString)), this, SLOT(moveFile(QString))))
    {
    QMessageBox Error;
    Error.setText("Connection unsuccesfull");
    Error.exec();
    }



  • @kingsta Hello,
    I too had problems in the past with signals and slots.
    If it is of any help, I followed a basic example and it worked fine. It declared the slot in the header, like this:

    loginWidget.h

    public slots:
        void verifyUser(int iUserCorrect )
        {
            if ( iUserCorrect != iUserVerified )
            {
                iUserVerified = iUserCorrect;
                emit loggedInRole(iUserVerified);
            }
        }
    
    signals:
        void loggedInRole(int iUserCorrect);
    
    private:
    int iUserVerified;
    

    Then, the connection was made with an instance of the loginWidget class in a mainWidget class:

    loginWidget* login = new loginWidget();
    
    connect(login, SIGNAL(loggedInRole(int)),
                this, SLOT(createInterface(int)));
    
    void mainWidget::createInterface(int iRole) {
    switch(iRole)
    {
    case 1: 
    //stuff
    break;
    
    case 2:
    //more stuff
    break;
    }
    }
    

    I hope this works for you as it did for me. I got to understand that variables are directly passed first by calling the first method/slot. This emits a signal, which carries a variable from the class. I haven't tried using variables that are not used inside the method that emits the signal, though. Finally, said variable is given as a parameter to the receiving slot. Maybe this is the issue in your case?



  • Hi friends. I read and tried all your posts. Firstly, thank you for effort. In no way, I can't find the solution... I can't understand, why doesn't it work? Where is my fault?

    @Paul-H. said:

    Did you call setAcceptDrops(true) in the DropArea constructor?

    Yes I call that function.
    Code;
    DropArea::DropArea(QWidget *parent)
    : QLabel(parent)
    {
    setMinimumSize(200, 200);
    setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
    setAlignment(Qt::AlignCenter);
    setAcceptDrops(true);
    setAutoFillBackground(true);
    clear();
    }

    @maximus said:

    Yes I would check that your signal is properly emitted first, put a debug message in "void DropArea::dropEvent(QDropEvent *event)" to see if you get there.
    Then put another message in the slot "void moveFile(QString path);" Should see where the problem is.
    Good luck!

    Good idea for controlling. Slot message doesn't show. But signal message shows in dropEvent(QDropEvent *event) function. Is that weird? I can't understand why??

    @darkp03 said:

    Another thing that you could do in order to check whats going on, is to verify if the connection was succesfully made. The connect method returns a bool. As i had many times problems with signals and slots, I always check this value, just to be sure. It would be something like this.

    if(!connect(dropArea, SIGNAL(fileDropped(QString)), this, SLOT(moveFile(QString))))
    {
    QMessageBox Error;
    Error.setText("Connection unsuccesfull");
    Error.exec();
    }

    I didn't know this method. Pretty good idea. I don't get the error message. I think connect function returns TRUE.

    @Jorge said:

    @kingsta Hello,
    I too had problems in the past with signals and slots.
    If it is of any help, I followed a basic example and it worked fine. It declared the slot in the header, like this:

    loginWidget.h

    public slots:
        void verifyUser(int iUserCorrect )
        {
            if ( iUserCorrect != iUserVerified )
            {
                iUserVerified = iUserCorrect;
                emit loggedInRole(iUserVerified);
            }
        }
    
    signals:
        void loggedInRole(int iUserCorrect);
    
    private:
    int iUserVerified;
    

    Then, the connection was made with an instance of the loginWidget class in a mainWidget class:

    loginWidget* login = new loginWidget();
    
    connect(login, SIGNAL(loggedInRole(int)),
                this, SLOT(createInterface(int)));
    
    void mainWidget::createInterface(int iRole) {
    switch(iRole)
    {
    case 1: 
    //stuff
    break;
    
    case 2:
    //more stuff
    break;
    }
    }
    

    I hope this works for you as it did for me. I got to understand that variables are directly passed first by calling the first method/slot. This emits a signal, which carries a variable from the class. I haven't tried using variables that are not used inside the method that emits the signal, though. Finally, said variable is given as a parameter to the receiving slot. Maybe this is the issue in your case?

    My signal and slot functions similar to your functions. Thank you for sharing functions. But my functions don't work.



  • Hey,

    So you get the debug message just before you emit the signal, but you don't get it in the slot "moveFile(QString)" ?
    Check that your Signal and Slot and properly linked, if you just make a typo in the connect it won't work.
    When your app start, look for a message with this text:

    QObject::connect: No such slot MainWindow::leftMenuChanged(int, int)
    do a search on this text in the console

    Good luck!



  • @Jorge said:

    connect(login, SIGNAL(loggedInRole(int)),
    this, SLOT(createInterface(int)));

    You were already advised to check the connection.
    I do not suggest to put any message as person above.
    This is overkill.
    But use Qt macro instead.
    For example:

    bool ok = connect(login, SIGNAL(loggedInRole(int)),
    this, SLOT(createInterface(int)));
    Q_ASSERT(ok );

    This will assert in debug.



  • @maximus said:

    Hey,

    So you get the debug message just before you emit the signal, but you don't get it in the slot "moveFile(QString)" ?
    Check that your Signal and Slot and properly linked, if you just make a typo in the connect it won't work.
    When your app start, look for a message with this text:

    QObject::connect: No such slot MainWindow::leftMenuChanged(int, int)
    do a search on this text in the console

    Good luck!

    Hi. Yes, absolutely. I don't get error message from connect. Everything looks nice but it doesn't work.

    @alex_malyu said:

    @Jorge said:

    connect(login, SIGNAL(loggedInRole(int)),
    this, SLOT(createInterface(int)));

    You were already advised to check the connection.
    I do not suggest to put any message as person above.
    This is overkill.
    But use Qt macro instead.
    For example:

    bool ok = connect(login, SIGNAL(loggedInRole(int)),
    this, SLOT(createInterface(int)));
    Q_ASSERT(ok );

    This will assert in debug.

    Hi. I write this code but App still doesn't work.



  • Guys I found the solution! I declared the DropArea widget with "Custom Widget with Qt Designer". The article. I changed the connect code below. It works!

    connect(ui->widget, SIGNAL(fileDropped(QString)), this, SLOT(moveFile(QString)));

    I didn't write before the custom widget thing, I am really sorry about that. I remember now... Your efforts teach me Signal&Slot mechanism in-depth. Thank all of you, really.

    Have a good day.


Log in to reply
 

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