Get a signal in a closeevent



  • Hello,

    I don't understand this problem, I generate in a closeevent function of a herited class mywidget from QWidget, a signal. But that signal is not emitted.

    Hete is the closeEvent function:

    
    void GLWidget::closeEvent(QCloseEvent *e)
    {
        qDebug() << "closeEvent(QCloseEvent *e)";
        QWidget::closeEvent(e);
        e->ignore();
    
        blockSignals(false);
        emit askToClosed(Name);
    }
    
    

    In that protected function the signal is not emitted but in the other function the signal works properly. Why?



  • @Xav12358 said in Get a signal in a closeevent:

    1. But that signal is not emitted.
    2. emit askToClosed(Name);
    3. In that protected function the signal is not emitted but in the other function the signal works properly. Why?

    Hi @Xav12358 ,

    1. How are you sure that the signal is not emitted?
    2. in askToClosed there is an argument Name, a connected slot this signal contain also same arg type?
      3)What is the other function where the signal works perfectly?


  • I am sure that the signal and slot is properly made because I use the same signal on other function in the same class and the slot works fine( I have a break point int it).

    But in that closeEvent function the signal don't generate a breakpoint in my slot function



  • @Xav12358 said in Get a signal in a closeevent:

    I am sure that the signal and slot is properly made because I use the same signal on other function in the same class and the slot works fine( I have a break point int it).

    But in that closeEvent function the signal don't generate a breakpoint in my slot function

    Can you share a sample code ?



  • #ifndef GLWIDGET_H
    #define GLWIDGET_H
    
    #include "include/CommonGUI.h"
    
    #include <QDebug>
    #include <QImage>
    #include <QLabel>
    #include <QPixmap>
    #include <QWidget>
    
    
    #include <stdio.h>
    #include <iostream>
    
    class GLWidget : public QWidget
    {
        Q_OBJECT
    
        int iIndexOfDisplayer_;
        QString Name;
    public:
        typedef enum {
            BGE_8UC3,BGE_8U,BGE_64F,BGE_32F
        }TYPEDATA;
        ///
        /// \brief GLWidget
        /// \param width
        /// \param height
        /// \param type
        /// \param parent
        ///
        explicit GLWidget(int width, int height, TYPEDATA type, int iIndexOfDisplayer, QWidget *parent = 0);
        ~GLWidget();
        ///
        /// \brief setDevice
        /// \param Device
        /// \param min
        /// \param max
        ///set data to QImage foreach type data
        void setDevice(uint8_t *Device, float min=0, float max=0);
      /*  QString getQStringIdWidget()
        {
            return QString::number(iIndexOfDisplayer_);
        }*/
    
    
        ///
        /// \brief view
        /// \param title
        ///Display Image in Qlabel
        void view();
        ///
        /// \brief resizeEvent
        /// \param event
        ///
        void resizeEvent ( QResizeEvent * event )
        {
            label_->setScaledContents(true);
            label_->resize(this->size());
        }
    
    protected:
        ///
        /// \brief closeEvent
        /// \param e
        /// emit index of GLWidget
        void closeEvent(QCloseEvent *e);
    
        void paintEvent(QPaintEvent *event)
        {
            qDebug() << "GLWidget::paintEvent In";
            if(!paintingActive())
                QWidget::paintEvent(event);
            qDebug() << "GLWidget::paintEvent Out";
        }
    private:
    
        TYPEDATA typeData_;
        QImage *Image_;
        int iwidth_,iheight_;
        QLabel *label_;
    
    public slots:
        void newImage(ImageUpdater);
    signals:
        void askToClosed(QString);
    };
    
    #endif // GLWIDGET_H
    
    
    
    
    
    #include "include/GLWidget.h"
    
    #include <QCloseEvent>
    #include <QDebug>
    
    GLWidget::GLWidget(int width, int height, TYPEDATA type,int iIndexOfDisplayer, QWidget *parent) :
        QWidget(parent),
        iIndexOfDisplayer_(iIndexOfDisplayer),
        iwidth_(width),
        iheight_(height)
    {
        typeData_ = type;
        label_ = new QLabel(this);
    
        setWindowFlags( Qt::WindowStaysOnTopHint );
    
    nane = "toto"
    
    }
    
    
    GLWidget::~GLWidget()
    {
        qDebug() << "Destroy GLWidget";
    }
    
    
    void GLWidget::view()
    {
        label_->setPixmap(QPixmap::fromImage(*Image_));
        setWindowTitle(Name);
    
        qDebug() << "GLWidget::view()";
        if(this->isHidden())
        {
            show();
            setFixedSize(640,480);
        }
    
        repaint();
    
    //    emit askToClosed(Name); //work
    }
    
    //////////////// SLOT /////////////////
    
    void GLWidget::newImage(ImageUpdater I)
    {
        if(I.iIndexOfDisplayer == iIndexOfDisplayer_)
        {
            setDevice(I.u8_pt,I.min, I.max);
            view();
        }
    }
    
    void GLWidget::closeEvent(QCloseEvent *e)
    {
        qDebug() << "closeEvent(QCloseEvent *e)";
        QWidget::closeEvent(e);
    //    //e->ignore();
    //    e->accept();
    //    blockSignals(false);
    
        emit askToClosed(Name); // don't work
    }
    
    


  • @Xav12358 said in Get a signal in a closeevent:

    #ifndef GLWIDGET_H
    #define GLWIDGET_H
    
    #include "include/CommonGUI.h"
    
    #include <QDebug>
    #include <QImage>
    #include <QLabel>
    #include <QPixmap>
    #include <QWidget>
    
    
    #include <stdio.h>
    #include <iostream>
    
    class GLWidget : public QWidget
    {
        Q_OBJECT
    
        int iIndexOfDisplayer_;
        QString Name;
    public:
        typedef enum {
            BGE_8UC3,BGE_8U,BGE_64F,BGE_32F
        }TYPEDATA;
        ///
        /// \brief GLWidget
        /// \param width
        /// \param height
        /// \param type
        /// \param parent
        ///
        explicit GLWidget(int width, int height, TYPEDATA type, int iIndexOfDisplayer, QWidget *parent = 0);
        ~GLWidget();
        ///
        /// \brief setDevice
        /// \param Device
        /// \param min
        /// \param max
        ///set data to QImage foreach type data
        void setDevice(uint8_t *Device, float min=0, float max=0);
      /*  QString getQStringIdWidget()
        {
            return QString::number(iIndexOfDisplayer_);
        }*/
    
    
        ///
        /// \brief view
        /// \param title
        ///Display Image in Qlabel
        void view();
        ///
        /// \brief resizeEvent
        /// \param event
        ///
        void resizeEvent ( QResizeEvent * event )
        {
            label_->setScaledContents(true);
            label_->resize(this->size());
        }
    
    protected:
        ///
        /// \brief closeEvent
        /// \param e
        /// emit index of GLWidget
        void closeEvent(QCloseEvent *e);
    
        void paintEvent(QPaintEvent *event)
        {
            qDebug() << "GLWidget::paintEvent In";
            if(!paintingActive())
                QWidget::paintEvent(event);
            qDebug() << "GLWidget::paintEvent Out";
        }
    private:
    
        TYPEDATA typeData_;
        QImage *Image_;
        int iwidth_,iheight_;
        QLabel *label_;
    
    public slots:
        void newImage(ImageUpdater);
    signals:
        void askToClosed(QString);
    };
    
    #endif // GLWIDGET_H
    
    
    
    
    
    #include "include/GLWidget.h"
    
    #include <QCloseEvent>
    #include <QDebug>
    
    GLWidget::GLWidget(int width, int height, TYPEDATA type,int iIndexOfDisplayer, QWidget *parent) :
        QWidget(parent),
        iIndexOfDisplayer_(iIndexOfDisplayer),
        iwidth_(width),
        iheight_(height)
    {
        typeData_ = type;
        label_ = new QLabel(this);
    
        setWindowFlags( Qt::WindowStaysOnTopHint );
    
    nane = "toto"
    
    }
    
    
    GLWidget::~GLWidget()
    {
        qDebug() << "Destroy GLWidget";
    }
    
    
    void GLWidget::view()
    {
        label_->setPixmap(QPixmap::fromImage(*Image_));
        setWindowTitle(Name);
    
        qDebug() << "GLWidget::view()";
        if(this->isHidden())
        {
            show();
            setFixedSize(640,480);
        }
    
        repaint();
    
    //    emit askToClosed(Name); //work
    }
    
    //////////////// SLOT /////////////////
    
    void GLWidget::newImage(ImageUpdater I)
    {
        if(I.iIndexOfDisplayer == iIndexOfDisplayer_)
        {
            setDevice(I.u8_pt,I.min, I.max);
            view();
        }
    }
    
    void GLWidget::closeEvent(QCloseEvent *e)
    {
        qDebug() << "closeEvent(QCloseEvent *e)";
        QWidget::closeEvent(e);
    //    //e->ignore();
    //    e->accept();
    //    blockSignals(false);
    
        emit askToClosed(Name); // don't work
    }
    
    

    Where your connection to slot is made?



  •         ```
    
    connect(myGL,SIGNAL(askToClosed(QString)),this,SLOT(askToClosed(QString)));
    ....
    
    void MainWindows::askToClosed(QString S)
    {
        qDebug() << "IAMHERE";
    }
    


  • I just made a sample that emit signal on CloseEvent , and this work without any problem for me, i used qt 5.8 and ubuntu 14

    MainWindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
    
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    

    MainWindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QDebug>
    #include <QCloseEvent>
    #include "widget.h"
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        Widget* w = new Widget(this);
    
        ui->verticalLayout->addWidget(w);
        w->show();
    
        connect(ui->pushButton,SIGNAL(clicked(bool)),w,SLOT(close()));
        connect(w,SIGNAL(widgetClosed()),this,SLOT(close()));
    }
    
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    Widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        void closeEvent(QCloseEvent* ev);
        ~Widget();
    
    signals:
        void widgetClosed();
    private:
        Ui::Widget *ui;
    };
    
    #endif // WIDGET_H
    

    Widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>
    #include <QCloseEvent>
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    }
    /**
     * @brief Widget::closeEvent
     * @param ev
     */
    void Widget::closeEvent(QCloseEvent *ev)
    {
    
        QWidget::closeEvent(ev);
        blockSignals(false);
        ev->ignore();
        qDebug() << Q_FUNC_INFO;
    
        emit widgetClosed();
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    

    I don't know what is the source of your problem ,

    Don't you have any output warnings or errors on application output?



  • What happens if you don't call

    QWidget::closeEvent(e);
    

    in your closeEvent? If the event is accepted and WA_DeleteOnCLose is set, your widget might be getting deleted before your signal is emitted. You could pass that event to the slot connected to your signal. Based on the name, I'm assuming your are asking the user if they really want to close the widget before it is actually closed.



  • Sorry for the late response.

    Here is the code, so I have a QObject called BGEPreviewWorker linked to a QThread and the BGEPreviewWorker get GLWindow to display things:

    class BGEPreviewWorker : public QObject
    {
        QHash<QString,GLWidget*> hashWidgetView; ///< list of display data
    
        Q_OBJECT
        int iwidth_;            ///< memorise the with of element to process
        int iheight_;           ///< memorise the height of element to process
    
        cv::Mat dx1_blur1;
        double min,max;
    
    
        QHash<QString,GLWidget*> hashWidgetView; ///< list of display data
    public:
    
        BGEPreviewWorker(QObject *parent = NULL);
        ~BGEPreviewWorker();
    
        ///
        /// \brief display function which collct all data in the gpu and display it
        ///
        void display();
    
    
    
    public slots:
        void work();
        void askToClosed(QString);
    
    signals:
    };
    
    
    BGEPreviewWorker::BGEPreviewWorker(QObject *parent):
        QObject(parent),
        iwidth_(1920),
        iheight_(1080),
        bIsRunning_(false),
        bIsInitialised_(false)
    {
    
    
    
    
        dx1_blur1.create(iheight_,iwidth_,CV_64F);
    
        hashWidgetView["save_Blur1"]        = new GLWidget(iwidth_,iheight_,GLWidget::BGE_64F,0);
    
    
    
        QHash<QString,GLWidget*>::iterator iter = hashWidgetView.begin();
        for(int i = 0;
            i<hashWidgetView.size();
            i++)
        {
            connect(this,SIGNAL(newImage(ImageUpdater)),((iter+i)).value(),SLOT(newImage(ImageUpdater)));
            
    
    connect((iter+i).value(),SIGNAL(askToClosed(QString)),this,SLOT(askToClosed(QString)));
    
            (iter+i).value()->show()
    
        }
    
    }
    
    

    Here is how I call the BGEPreviewWorker with the QThread

        BGEPreviewWorker *BGEWork = new BGEPreviewWorker();
       QThread*  BGEThread = new QThread();
        BGEWork->moveToThread(BGEThread);
    
        connect(BGEThread, SIGNAL(started()), BGEWork, SLOT(work()) );
    

    But the askToClosed never goes to the askToClosed slot of BGEPreviewWorker ... why?


  • Moderators

    @Xav12358 said in Get a signal in a closeevent:

    connect((iter+i).value(),SIGNAL(askToClosed(QString)),this,SLOT(askToClosed(QString)));

    You should check the return value of this connect call to be sure it was actually connected.
    Also are you sure the askToClosed signal was emitted?



  • Yes the signal is well emitted.

    I finally find the root of the problem.

    When I don't put the object into the Qthread ("BGEWork->moveToThread(BGEThread);") it works, but when I add the line the signal is not received by the BGEPreviewWorker.
    A QObject place into a QThread can't receive a signal?


  • Qt Champions 2016

    @Xav12358
    Hi make sure you specify QueuedConnection for the signal when doing the connect.
    This is needed when between threads. The default is Auto Connection so it should do by itself but its worth checking.

    There is section here about it
    http://doc.qt.io/qt-5/threads-qobject.html



  • I change the connection function :

                connect((iter+i).value(),SIGNAL(askToClosed(QString)),this,SLOT(askToClosed(QString)), Qt::DirectConnection);
    
    

    And now it works



  • @Xav12358 said in Get a signal in a closeevent:

    I change the connection function :

                connect((iter+i).value(),SIGNAL(askToClosed(QString)),this,SLOT(askToClosed(QString)), Qt::DirectConnection);
    
    

    And now it works

    I am not sure that this is what you want, since you are using moveToThread(aNewThread) from this object i think that you want run this slot on your aNewThread, and this is not the case for DirectConnection

    Signals and Slots Across Threads

    Qt supports these signal-slot connection types:
    .
    .
    .

    Direct Connection The slot is invoked immediately, when the signal is emitted.
    

    The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.

    Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. 
    

    The slot is executed in the receiver's thread.
    .
    .
    .

    As suggested by @mrjj , i think also that you have to use QueuedConnection


Log in to reply