Solved QComboBox - unhandled exception if combobox was expanded (drop-down)
-
Hi,
Which version of Qt are you using ?
On which version of Windows ?
With which compiler ? -
Qt5.4
Win7Pro
Microsoft Visual Studio 2010 -
Are you locked to these outdated version of both Qt and Visual Studio ?
-
To Visual Studio - yes, because other library, I use, have only version for VS2010 (there is no newer version of that library unfortunately).
To Qt - I don't know how much it changed and I would have to change all my code which could cause errors hard to find if I make a simple mistake. So I'd rahter not change if it is unnecessary. -
Fair enough (I know that problem...)
By the way, what graphic card are you using ?
-
@never_ever said in QComboBox - unhandled exception if combobox was expanded (drop-down):
To Visual Studio - yes, because other library, I use, have only version for VS2010 (there is no newer version of that library unfortunately).
To Qt - I don't know how much it changed and I would have to change all my code which could cause errors hard to find if I make a simple mistake. So I'd rahter not change if it is unnecessary.If you need to stick at VS2010, there is not much Qt upgrade possibility (I don't know for Qt 5.5, but 5.6 does not support VS2010 anymore IIRC).
Anyway, I'm still using Qt 4.8, VS2010 and comboboxes. Are you sure the crash is not related to your code?
- What happens if you add the items already in designer?
- Is the subwindow already created when you add the items [i.e. is ui->setupUi() called?]
-
@SGaist NVIDIA GeForce GTX 760
@aha_1980 If I add the items in designer I get the same exception (but this exception shows only if I activate combobox - by pop up list. If I do not use combobox there no exception is shown).
To your second question: yes, subwindow is already created when I add items .
I am not 100% sure that it is not related to my code but I am 95% sure because as I wrote above I have only this two lines of code related to comboxes:ui.cbLeftCam->addItems(QStringList()<<"1"<<"2"<<"3"); ui.cbRightCam->addItems(QStringList()<<"a"<<"b"<<"c");
I do not use any signals from comboboxes.
Before I added them everything was ok (now if I don't activate them it also works fine) -
@never_ever: Can you show your code? Otherwise it's just guessing from our side...
Best would be to boil this down to a minimal working example. On that way, most bugs disappear magically :)
-
It's my code that I simplify (it also crashes). TestComboBox class is main window, and from it I can call subwindow Calibration.
Calibration.h
class Calibration : public QWidget { Q_OBJECT public: static Calibration* Instance(); void changeViewToCalib(); void changeViewToCatch(); void changeToOffline(bool isOffline); signals: void calibrationStarted(bool started); protected: void closeEvent(QCloseEvent* event); private: Calibration(QWidget *parent = 0); ~Calibration(); Calibration(Calibration const&); void operator=(Calibration const&); bool checkCalibrationChoice(); void showEvent(QShowEvent*event); private slots: void closeWindowSlot(); void setSingleCalibrationSlot(bool checked); void setStereoCalibrationSlot(bool checked); void stopCalibSlot(); private: Ui::Calibration ui; QString m_firstCamId; QString m_secondCamId; QCheckBox* m_boxStereo; QCheckBox* m_boxSingle; bool m_offline; bool m_calibImages; bool m_stereoCalibration; bool m_calibStopped; };
Calibration.cpp
Calibration* Calibration::Instance() { static Calibration obj; return &obj; } void Calibration::changeViewToCalib() { setWindowTitle(tr("Calibration")); ui.tabWidget->setTabText(0, tr("Calibration process")); ui.gbProcessType->setTitle(tr("Calibration type")); } void Calibration::changeViewToCatch() { setWindowTitle(tr("Catching images")); ui.tabWidget->setTabText(0, tr("Catching process")); ui.gbProcessType->setTitle(tr("Catching type")); } void Calibration::changeToOffline(bool isOffline) { if(isOffline) { m_offline = true; } else { m_offline = false; } } void Calibration::closeEvent(QCloseEvent* event) { stopCalibSlot(); event->accept(); } Calibration::Calibration(QWidget *parent) : QWidget(parent) { ui.setupUi(this); connect(ui.pbCloseCalibWindow, SIGNAL(clicked()), this, SLOT(closeWindowSlot())); } Calibration::~Calibration() { } bool Calibration::checkCalibrationChoice() { m_firstCamId = m_secondCamId = QString(); if(m_boxStereo->isChecked() && (!m_offline || (m_offline && !m_calibImages))) { int leftIndex = 0; //TEST: ui.cbLeftCam->currentIndex(); int rightIndex = 0; //TEST: ui.cbRightCam->currentIndex(); if(leftIndex == rightIndex) { QMessageBox msg; msg.setText(tr("Error! \nThe same cameras was chosen.")); msg.exec(); return false; } else { m_stereoCalibration = true; m_firstCamId = "";//TEST: ui.cbLeftCam->currentText(); m_secondCamId = "";//TEST: ui.cbRightCam->currentText(); return true; } } else if(m_boxSingle->isChecked()/* && !m_offline*/) { m_stereoCalibration = false; m_firstCamId = ""; //TEST: ui.cbLeftCam->currentText(); return true; } else if(m_offline) { if(m_boxSingle->isChecked()) { m_stereoCalibration = false; return true; } else if(m_boxStereo->isChecked()) { m_stereoCalibration = true; return true; } else return false; } else { QMessageBox msg; msg.setText(tr("Type of calibration not selected")); msg.exec(); return false; } } void Calibration::showEvent(QShowEvent*event) { static bool firstShow = true; // Calibration from loaded images if(m_calibImages) { //QGroupBox* typeCalibBox = new QGroupBox(tr("Choose calibration type"), ui.menuWidget); m_boxSingle = new QCheckBox(tr("Single camera")); m_boxStereo = new QCheckBox(tr("Stereo camera")); } // Calibration from view from cameras or catching images // Create menu to pick calibration type and camera else { if(firstShow) { m_boxSingle = new QCheckBox(tr("Single camera")); m_boxStereo = new QCheckBox(tr("Stereo camera")); QVBoxLayout* vBoxType = new QVBoxLayout(); vBoxType->addWidget(m_boxSingle); vBoxType->addWidget(m_boxStereo); ui.gbProcessType->setLayout(vBoxType); QButtonGroup* typeCalibGroup = new QButtonGroup(ui.gbProcessType); typeCalibGroup->addButton(m_boxSingle); typeCalibGroup->addButton(m_boxStereo); if(!m_calibImages) { connect(m_boxSingle, SIGNAL(toggled(bool)), this, SLOT(setSingleCalibrationSlot(bool))); connect(m_boxStereo, SIGNAL(toggled(bool)), this, SLOT(setStereoCalibrationSlot(bool))); //m_camerasList.clear(); //ui.cbLeftCam->clear(); //ui.cbRightCam->clear(); //ui.cbLeftCam->addItem(tr("Choose left camera...")); //ui.cbRightCam->addItem(tr("Choose right camera...")); ui.cbLeftCam->addItems(QStringList()<<"1"<<"2"<<"3"); ui.cbRightCam->addItems(QStringList()<<"a"<<"b"<<"c"); } m_boxSingle->setChecked(true); ui.cbRightCam->hide(); typeCalibGroup->setExclusive(true); } } QWidget::showEvent(event); m_calibStopped = true; } void Calibration::closeWindowSlot() { stopCalibSlot(); close(); } void Calibration::setSingleCalibrationSlot(bool checked) { ui.cbRightCam->hide(); } void Calibration::setStereoCalibrationSlot(bool checked) { ui.cbRightCam->show(); } void Calibration::stopCalibSlot() { if(m_calibStopped) { emit calibrationStarted(false); return; } m_calibStopped = true; }
TestComboBox.h
class testComboBox : public QMainWindow { Q_OBJECT public: testComboBox(QWidget *parent = 0); ~testComboBox(); public slots: void catchImages(); void setCameraCaptureState(bool isCaptured); private: Ui::testComboBoxClass ui; bool m_calibrationStarted; };
TestComboBox.cpp
testComboBox::testComboBox(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); connect(ui.actionImages, SIGNAL(triggered()), this, SLOT(catchImages())); connect(Calibration::Instance(), SIGNAL(calibrationStarted(bool)), this, SLOT(setCameraCaptureState(bool)), Qt::UniqueConnection); } testComboBox::~testComboBox(){} void testComboBox::catchImages() { if(m_calibrationStarted) { QMessageBox::warning(this, tr("Warning"), tr("Capture in progress! \nIf you want make changes stop process."), QMessageBox::Ok); return; } Calibration::Instance()->changeViewToCatch(); Calibration::Instance()->changeToOffline(true); Calibration::Instance()->show(); } void testComboBox::setCameraCaptureState(bool isCaptured) { m_calibrationStarted = isCaptured; }
-
The problem is with the static instance of
Calibration
. Many of Qt's internal mechanisms rely on the existance of application object. Since static variables are destroyed aftermain()
exits the application instance is no longer there.
Instances ofQObject
derived classes should never outlive the application object.If you need a
QObject
derived singleton use a static pointer and release it before you exit application object's scope, e.g.Calibration* Calibration::Instance() { static Calibration* obj = nullptr; if (!obj) { obj = new Calibration(); conntect(qApp, &QCoreApplication::aboutToQuit, obj, &Calibration::deleteLater); } return obj; }
-
Thanks, it really helps.
-
@never_ever I met the same problem and use
exit()
instead ofreturn a.exec()
, program can exit normally -
@trreeee
And as I wrote you in your topic for that it is a bad idea to useexit()
rather than fixing your destructor code, so should not be recommended to other people. And I see @Chris-Kawa above recommends the same as I did there:If you need a QObject derived singleton use a static pointer and release it before you exit application object's scope