Unsolved 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 }
-
@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?
-
@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? -
@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 DirectConnectionSignals 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