From 7ce53adac9744d666ae89a26ee24600b168d8cea Mon Sep 17 00:00:00 2001 From: Yannick Verdie Date: Wed, 28 Jul 2010 20:59:41 +0000 Subject: [PATCH] Qt: Fixed bug with exclusive buttons Fixed memory leaks --- modules/highgui/src/window_QT.cpp | 100 +++++++++++++++++++++--------- modules/highgui/src/window_QT.h | 13 ++-- 2 files changed, 79 insertions(+), 34 deletions(-) diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index caaa0ab1f..9d904e88e 100755 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -244,8 +244,12 @@ CV_IMPL int cvInitSystem( int, char** ) CV_IMPL int cvWaitKey( int arg ) { + int result = -1; + if (!guiMainThread) + return result; + unsigned long delayms;//in milliseconds if (arg<=0) delayms = ULONG_MAX; @@ -266,12 +270,8 @@ CV_IMPL int cvWaitKey( int arg ) //cannot use wait here because events will not be distributed before processEvents (the main eventLoop is broken) //so I create a Thread for the QTimer - QTimer timer(guiMainThread); - QObject::connect(&timer, SIGNAL(timeout()), guiMainThread, SLOT(timeOut())); - timer.setSingleShot(true); - if (arg>0) - timer.start(arg); + guiMainThread->timer->start(arg); //QMutex dummy; @@ -279,12 +279,16 @@ CV_IMPL int cvWaitKey( int arg ) { qApp->processEvents(QEventLoop::AllEvents); + + if (!guiMainThread)//when all the windows are deleted + return result; + mutexKey.lock(); if (last_key != -1) { result = last_key; last_key = -1; - timer.stop(); + guiMainThread->timer->stop(); //printf("keypressed\n"); } mutexKey.unlock(); @@ -302,10 +306,12 @@ CV_IMPL int cvWaitKey( int arg ) waitCondition.wait(&dummy, 2); */ + //to decrease CPU usage + //sleep 1 millisecond #if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 - Sleep(2); + Sleep(1); #else - usleep(2);//to decrease CPU usage + usleep(1000); #endif } @@ -329,6 +335,7 @@ CV_IMPL int cvStartLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* CV_IMPL void cvStopLoop() { + qApp->exit(); } @@ -336,13 +343,14 @@ CV_IMPL void cvStopLoop() CvWindow* icvFindWindowByName( const char* arg ) { - QPointer window = NULL; + QPointer window; if( !arg ) CV_Error( CV_StsNullPtr, "NULL name string" ); QString name(arg); - QPointer w; + CvWindow* w; + foreach (QWidget *widget, QApplication::topLevelWidgets()) { @@ -357,6 +365,7 @@ CvWindow* icvFindWindowByName( const char* arg ) } } + return window; } @@ -473,6 +482,8 @@ CV_IMPL void cvDestroyWindow( const char* name ) ); } + + CV_IMPL void cvDestroyAllWindows(void) { if (!guiMainThread) @@ -657,10 +668,29 @@ CV_IMPL void cvShowImage( const char* name, const CvArr* arr ) //----------OBJECT---------------- -GuiReceiver::GuiReceiver() : _bTimeOut(false) +GuiReceiver::GuiReceiver() : _bTimeOut(false), nb_windows(0) { icvInitSystem(); - //qApp->setQuitOnLastWindowClosed ( false );//maybe the user would like to access this setting + + timer = new QTimer; + QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timeOut())); + timer->setSingleShot(true); +} + + +void GuiReceiver::isLastWindow() +{ + if (--nb_windows <= 0) + { + delete guiMainThread; + guiMainThread = NULL; + qApp->quit(); + } +} + +GuiReceiver::~GuiReceiver() +{ + delete timer; } void GuiReceiver::putText(void* arg1, QString text, QPoint org, void* arg2) @@ -826,6 +856,7 @@ void GuiReceiver::createWindow( QString name, int flags ) } //QPointer w1 = + nb_windows++; new CvWindow(name, flags); } @@ -896,13 +927,15 @@ void GuiReceiver::destroyAllWindow() { qApp->closeAllWindows(); }else{ - QPointer w; - foreach (QWidget *widget, QApplication::topLevelWidgets()) + + foreach (QObject *obj, QApplication::topLevelWidgets()) { - w = (CvWindow*) widget; - w->close(); - delete w; + if (obj->metaObject ()->className () == "CvWindow") + { + delete obj; + } } + } } @@ -1135,23 +1168,20 @@ void CvButtonbar::addButton( QString name, CvButtonCallback call, void* userdata QPointer button; if (button_type == CV_PUSH_BUTTON) - //CvPushButton* button = (QAbstractButton*) new CvPushButton(this, button_name,call, userdata); if (button_type == CV_CHECKBOX) - //CvCheckButton* button = (QAbstractButton*) new CvCheckBox(this, button_name,call, userdata, initial_button_state); if (button_type == CV_RADIOBOX) { - //CvCheckButton* button = (QAbstractButton*) new CvRadioButton(this, button_name,call, userdata, initial_button_state); group_button->addButton(button); } if (button) { - QObject::connect( button, SIGNAL( clicked() ),button, SLOT( callCallBack() )); + QObject::connect( button, SIGNAL( toggled(bool) ),button, SLOT( callCallBack(bool) )); addWidget(button,Qt::AlignCenter); } } @@ -1170,12 +1200,15 @@ CvPushButton::CvPushButton(CvButtonbar* arg1, QString arg2, CvButtonCallback arg setObjectName(button_name); setText(button_name); + + if (isChecked()) + callCallBack(true); } -void CvPushButton::callCallBack() +void CvPushButton::callCallBack(bool checked) { if (callback) - callback(-1,userdata); + callback(checked,userdata); } CvCheckBox::CvCheckBox(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, void* arg4, int initial_button_state) @@ -1188,12 +1221,15 @@ CvCheckBox::CvCheckBox(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, v setObjectName(button_name); setCheckState((initial_button_state == 1?Qt::Checked:Qt::Unchecked)); setText(button_name); + + if (isChecked()) + callCallBack(true); } -void CvCheckBox::callCallBack() +void CvCheckBox::callCallBack(bool checked) { if (callback) - callback(this->isChecked(),userdata); + callback(checked,userdata); } CvRadioButton::CvRadioButton(CvButtonbar* arg1, QString arg2, CvButtonCallback arg3, void* arg4, int initial_button_state) @@ -1206,12 +1242,15 @@ CvRadioButton::CvRadioButton(CvButtonbar* arg1, QString arg2, CvButtonCallback a setObjectName(button_name); setChecked(initial_button_state); setText(button_name); + + if (isChecked()) + callCallBack(true); } -void CvRadioButton::callCallBack() +void CvRadioButton::callCallBack(bool checked) { if (callback) - callback(this->isChecked(),userdata); + callback(checked,userdata); } @@ -1390,6 +1429,9 @@ CvWindow::~CvWindow() for (int i=0;iisLastWindow(); } @@ -1497,7 +1539,7 @@ void CvWindow::createActions() void CvWindow::createToolBar() { - myToolBar = new QToolBar; + myToolBar = new QToolBar(this); myToolBar->setFloatable(false);//is not a window myToolBar->setMaximumHeight(28); @@ -1507,7 +1549,7 @@ void CvWindow::createToolBar() void CvWindow::createStatusBar() { - myStatusBar = new QStatusBar; + myStatusBar = new QStatusBar(this); myStatusBar->setSizeGripEnabled(false); myStatusBar->setMaximumHeight(20); myStatusBar_msg = new QLabel; diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 935e7f279..a824e837b 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -109,11 +109,15 @@ class GuiReceiver : public QObject public: GuiReceiver(); + ~GuiReceiver(); int start(); + void isLastWindow(); + bool _bTimeOut; + QTimer *timer; private: - + int nb_windows; public slots: void createWindow( QString name, int flags = 0 ); @@ -137,7 +141,6 @@ public slots: void setOpenGLCallback(QString window_name, void* callbackOpenGL, void* userdata, double angle, double zmin, double zmax); void putText(void* arg1, QString text, QPoint org, void* font); void addButton(QString button_name, int button_type, int initial_button_state , void* on_change, void* userdata); - }; enum typeBar{type_CvTrackbar = 0, type_CvButtonbar = 1}; @@ -179,7 +182,7 @@ private: void* userdata; private slots: - void callCallBack(); + void callCallBack(bool); }; @@ -197,7 +200,7 @@ private: void* userdata; private slots: - void callCallBack(); + void callCallBack(bool); }; class CvRadioButton : public QRadioButton @@ -213,7 +216,7 @@ private: void* userdata; private slots: - void callCallBack(); + void callCallBack(bool); };