App crashes when using findChild<> in Qt
-
Nothing is there in my .ui file. In
mainwindow.cppI'm just adding one widgetTestinside which I'm adding one labelTLabel
mainwindow.cpp:#include "mainwindow.h" #include "ui_mainwindow.h" #include "QDebug" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); Test = new QWidget(this); TLayout = new QVBoxLayout(Test); TLayout->setContentsMargins(0,0,0,0); TLayout->setSpacing(2); TLabel = new QLabel(Test); TLabel->setObjectName("MyLabel"); TLabel->setText("Done Task!!"); TLayout->addWidget(TLabel); Test->setLayout(TLayout); MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); QWidget* list1 = app->Test->findChild<QWidget*>("MyLabel"); qDebug()<<list1; } MainWindow::~MainWindow() { delete ui; }When I'm trying to access
TLabelusing findChild<> method, it shows:Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe ... 11:56:32: The program has unexpectedly finished. 11:56:32: The process was ended forcefully. 11:56:32: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed. -
Nothing is there in my .ui file. In
mainwindow.cppI'm just adding one widgetTestinside which I'm adding one labelTLabel
mainwindow.cpp:#include "mainwindow.h" #include "ui_mainwindow.h" #include "QDebug" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); Test = new QWidget(this); TLayout = new QVBoxLayout(Test); TLayout->setContentsMargins(0,0,0,0); TLayout->setSpacing(2); TLabel = new QLabel(Test); TLabel->setObjectName("MyLabel"); TLabel->setText("Done Task!!"); TLayout->addWidget(TLabel); Test->setLayout(TLayout); MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); QWidget* list1 = app->Test->findChild<QWidget*>("MyLabel"); qDebug()<<list1; } MainWindow::~MainWindow() { delete ui; }When I'm trying to access
TLabelusing findChild<> method, it shows:Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe ... 11:56:32: The program has unexpectedly finished. 11:56:32: The process was ended forcefully. 11:56:32: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.@Meera-Hadid said in App crashes when using findChild<> in Qt:
Nothing is there in my .ui file. In
mainwindow.cppI'm just adding one widgetTestinside which I'm adding one labelTLabel
mainwindow.cpp:MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{...
MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); QWidget* list1 = app->Test->findChild<QWidget*>("MyLabel");...
MainWindow appears to be derived from QMainWindow. QApplication::instance() returns a QApplication *. Therefore, qobject_cast<MainWindow*>(QApplication::instance()) will return
nullptr.
(nullptr)->Test is an invalid dereference, leading to:Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe ... 11:56:32: The program has unexpectedly finished. 11:56:32: The process was ended forcefully. 11:56:32: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.Perhaps
this->Test->findChild(), orTest->findChild()is what you're looking for. -
My main aim is I want to access the widgets of the
mainwindow.uifile in other class(form.cxx)mainwindow.cxx:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "QDebug" #include "form.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); Test = new QWidget(this); TLayout = new QVBoxLayout(Test); TLayout->setContentsMargins(0,0,0,0); TLayout->setSpacing(2); TLabel = new QLabel(Test); TLabel->setObjectName("MyLabel"); TLabel->setText("Done Task!!"); TLayout->addWidget(TLabel); Test->setLayout(TLayout); } MainWindow::~MainWindow() { delete ui; } MainWindow* MainWindow::Get() { MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); return app; } void MainWindow::on_pushButton_4_clicked() { Form* temp = new Form(this); temp->show(); }form.cxx:
#include "form.h" #include "ui_form.h" #include "mainwindow.h" #include "QDebug" Form::Form(QWidget *parent) : QWidget(parent), ui(new Ui::Form) { ui->setupUi(this); QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>(); qDebug() <<"myList: "<<myList; } Form::~Form() { delete ui; }when I click on the
on_pushButton_4button the window of the form.ui file doesn't open
it shows error:13:47:20: The program has unexpectedly finished. 13:47:20: The process was ended forcefully. 13:47:20: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.the error is because of this
QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();line and I don't know any other alternative solution for this problem. -
My main aim is I want to access the widgets of the
mainwindow.uifile in other class(form.cxx)mainwindow.cxx:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "QDebug" #include "form.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); Test = new QWidget(this); TLayout = new QVBoxLayout(Test); TLayout->setContentsMargins(0,0,0,0); TLayout->setSpacing(2); TLabel = new QLabel(Test); TLabel->setObjectName("MyLabel"); TLabel->setText("Done Task!!"); TLayout->addWidget(TLabel); Test->setLayout(TLayout); } MainWindow::~MainWindow() { delete ui; } MainWindow* MainWindow::Get() { MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); return app; } void MainWindow::on_pushButton_4_clicked() { Form* temp = new Form(this); temp->show(); }form.cxx:
#include "form.h" #include "ui_form.h" #include "mainwindow.h" #include "QDebug" Form::Form(QWidget *parent) : QWidget(parent), ui(new Ui::Form) { ui->setupUi(this); QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>(); qDebug() <<"myList: "<<myList; } Form::~Form() { delete ui; }when I click on the
on_pushButton_4button the window of the form.ui file doesn't open
it shows error:13:47:20: The program has unexpectedly finished. 13:47:20: The process was ended forcefully. 13:47:20: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.the error is because of this
QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();line and I don't know any other alternative solution for this problem.@Meera-Hadid said in App crashes when using findChild<> in Qt:
My main aim is I want to access the widgets of the
mainwindow.uifile in other class(form.cxx)mainwindow.cxx:
MainWindow* MainWindow::Get() { MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); return app; }Moving this code from the constructor to a member function doesn't change the fact that the QApplication instance is not a MainWindow. Using qobject_cast to attempt to turn it into one will always return a null pointer.
when I click on the
on_pushButton_4button the window of the form.ui file doesn't open
it shows error:13:47:20: The program has unexpectedly finished. 13:47:20: The process was ended forcefully. 13:47:20: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.the error is because of this
QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();line and I don't know any other alternative way for this problem.If there is only one MainWindow, track that instance in a variable and use it directly. If there can be multiple instances, iterating through QApplication::topLevelWidgets() is an option.
-
Hey, I'm new to Qt can you please demonstrate the code or give any references for this problem.
-
Hey, I'm new to Qt can you please demonstrate the code or give any references for this problem.
@Meera-Hadid
Having some other widget (Form) attempting to access aQMainWindow, or attempting to access anything on that main window, is indicative of a bad approach. Descendant widgets should not know, or need to now, about ancestor widgets.QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();is not a good approach, and should not be necessary.Why does
Formneed to do this, what is it trying to achieve and why? If anythingMainWindowshould be doing this work. InsteadMainWindowmight pass the required widget toForm, orFormmight emit a signal whichMainWindowhas a slot onto to do its work. Redesign your code to take a different approach. -
@Meera-Hadid
Having some other widget (Form) attempting to access aQMainWindow, or attempting to access anything on that main window, is indicative of a bad approach. Descendant widgets should not know, or need to now, about ancestor widgets.QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();is not a good approach, and should not be necessary.Why does
Formneed to do this, what is it trying to achieve and why? If anythingMainWindowshould be doing this work. InsteadMainWindowmight pass the required widget toForm, orFormmight emit a signal whichMainWindowhas a slot onto to do its work. Redesign your code to take a different approach.@JonB
I have a QToolButton in mymainwindow.uifile, all of it's dependencies are defined inmainwindow.cppfile. I want to make copy of this QToolButton inform.cppwhich is not directly related tomainwindow.cpp.So is there a solution for this problem.
-
@JonB
I have a QToolButton in mymainwindow.uifile, all of it's dependencies are defined inmainwindow.cppfile. I want to make copy of this QToolButton inform.cppwhich is not directly related tomainwindow.cpp.So is there a solution for this problem.
@Meera-Hadid
Hi- I want to make copy of this QToolButton in form.cpp
you cannot copy widgets. if you assigned the button from mainwindow to "form", it will be torn out of the
mainwindow and moved into form.- it's dependencies are defined in mainwindow.cpp
What would those be ?
Did you set it up in Designer and want to reuse this setup in a new widget ?
Or do you really want the button in Form to call functions in mainwindow ?
-
@JonB
I have a QToolButton in mymainwindow.uifile, all of it's dependencies are defined inmainwindow.cppfile. I want to make copy of this QToolButton inform.cppwhich is not directly related tomainwindow.cpp.So is there a solution for this problem.
@Meera-Hadid
Sounds a bit fishy, if whatever you mean by "all of it's dependencies are defined inmainwindow.cppfile" implies that theQToolButtonwill not function standalone inFormwithout having theMainWindowin existence. In theory we likeFormto be a standalone whatever-it-is, so it could be used even if you didn't have the main window. That would call for some sort of reorganization like making it its own widget or putting whatever code it needs into a shared file.Having said that, from where you are now still get rid of
MainWindow* MainWindow::Get()method/approach. If really necessary have theMainWindowcreate the copy of theQToolbarand pass it toForm(might be via the constructor, might be via aset()ter method exported fromForm). Or pass whatever parameters are necessary to create theQToolbarinForm. Either way makeMainFormexport something toForminstead of havingFormtry to accessMainWindow. -
code for QToolButton in
mainwindow.cppfile:this->FitToWindowToolButton = new QToolButton(q); this->FitToWindowToolButton->setObjectName("FitToWindowToolButton"); this->FitToWindowToolButton->setAutoRaise(true); this->FitToWindowToolButton->setDefaultAction(this->actionFit_to_window); this->FitToWindowToolButton->setFixedSize(15, 15); QObject::connect(this->actionFit_to_window, SIGNAL(triggered()), q, SLOT(fitSliceToBackground())); void qMRMLSliceControllerWidget::fitSliceToBackground() { Q_D(qMRMLSliceControllerWidget); d->SliceLogic->StartSliceNodeInteraction(vtkMRMLSliceNode::ResetFieldOfViewFlag); d->SliceLogic->FitSliceToAll(); d->MRMLSliceNode->UpdateMatrices(); d->SliceLogic->EndSliceNodeInteraction(); }As you can see the action of this
QToolButtonis linked with a function calledfitSliceToBackground()which is linked with other function inmainwindow.cppso it becomes difficult for me to creat aQToolButtoninForm.cppfrom scratch, hence I just want to export this button toForm.cpp. -
code for QToolButton in
mainwindow.cppfile:this->FitToWindowToolButton = new QToolButton(q); this->FitToWindowToolButton->setObjectName("FitToWindowToolButton"); this->FitToWindowToolButton->setAutoRaise(true); this->FitToWindowToolButton->setDefaultAction(this->actionFit_to_window); this->FitToWindowToolButton->setFixedSize(15, 15); QObject::connect(this->actionFit_to_window, SIGNAL(triggered()), q, SLOT(fitSliceToBackground())); void qMRMLSliceControllerWidget::fitSliceToBackground() { Q_D(qMRMLSliceControllerWidget); d->SliceLogic->StartSliceNodeInteraction(vtkMRMLSliceNode::ResetFieldOfViewFlag); d->SliceLogic->FitSliceToAll(); d->MRMLSliceNode->UpdateMatrices(); d->SliceLogic->EndSliceNodeInteraction(); }As you can see the action of this
QToolButtonis linked with a function calledfitSliceToBackground()which is linked with other function inmainwindow.cppso it becomes difficult for me to creat aQToolButtoninForm.cppfrom scratch, hence I just want to export this button toForm.cpp.@Meera-Hadid
But that's precisely the wrong thing to do. If you really have aQToolbarwhich can only function if it calls something inMainWindowthen you cannot/should not attempt to use it inForm.a function called
fitSliceToBackground()which is linked with other function inmainwindow.cppGlancing I cannot see what in
void qMRMLSliceControllerWidget::fitSliceToBackground()is linked to anything inmainwindow.cpp.In any case it's up to you refactor as necessary. You cannot/must not do what you are seeming to want to do.
On top of everything else, as @mrjj observed you can neither directly copy a
QToolbarorQToolbutton, nor can you "re-use" an existing one outside of their parent. -
Hi
If you really insist on calling to MainWindow then
you could define a new public signal in New Form.then connect
this new signal to q fitSliceToBackground slot in mainwindowThen your NEW button can trigger the same as FitToWindowToolButton from the other form.
void MainWindow::on_pushButton_4_clicked() { Form* temp = new Form(this); QObject::connect(temp, SIGNAL(MySignal()),q, SLOT(fitSliceToBackground())); temp->show(); }then in Form .h
signals:
void MySignal();in form.cpp
for the new toolbutton clickedvoid Form::on_newToolButton_clicked() { emit MySignal(); // send signal to main } -
My main aim is I want to access the widgets of the
mainwindow.uifile in other class(form.cxx)mainwindow.cxx:
#include "mainwindow.h" #include "ui_mainwindow.h" #include "QDebug" #include "form.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); Test = new QWidget(this); TLayout = new QVBoxLayout(Test); TLayout->setContentsMargins(0,0,0,0); TLayout->setSpacing(2); TLabel = new QLabel(Test); TLabel->setObjectName("MyLabel"); TLabel->setText("Done Task!!"); TLayout->addWidget(TLabel); Test->setLayout(TLayout); } MainWindow::~MainWindow() { delete ui; } MainWindow* MainWindow::Get() { MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance()); return app; } void MainWindow::on_pushButton_4_clicked() { Form* temp = new Form(this); temp->show(); }form.cxx:
#include "form.h" #include "ui_form.h" #include "mainwindow.h" #include "QDebug" Form::Form(QWidget *parent) : QWidget(parent), ui(new Ui::Form) { ui->setupUi(this); QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>(); qDebug() <<"myList: "<<myList; } Form::~Form() { delete ui; }when I click on the
on_pushButton_4button the window of the form.ui file doesn't open
it shows error:13:47:20: The program has unexpectedly finished. 13:47:20: The process was ended forcefully. 13:47:20: C:\Users\Meera\OneDrive\Desktop\build-untitled-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\untitled.exe crashed.the error is because of this
QWidget* myList = MainWindow::Get()->Test->findChild<QWidget*>();line and I don't know any other alternative solution for this problem.@Meera-Hadid said in App crashes when using findChild<> in Qt:
MainWindow* MainWindow::Get() {
MainWindow* app = qobject_cast<MainWindow*>(QApplication::instance());
return app;
}void MainWindow::on_pushButton_4_clicked()
{
Form* temp = new Form(this);
temp->show();
}You should listen to the others, but I will still answer to the approach you are trying so far. First of all: Drop
MainWindow::Get()! There is no way around this. AMainWindowis aMainWindowand aQApplicationis aQApplication. Casting between the two will never work. In Qt you have aQApplicationobject and usually a main window. You could also have no main window or several. So, it is up to you to make main window known to others.The worst solution to this is to use the Singleton pattern. Currently, there is a trend to discourage the Singleton pattern in any form whatsoever in C++. Though this would certainly solve your problem as long as you only have a single main window. (The reason why the use of Singletons is discouraged is because of testing.)
A slightly better solution is that you already pass
this(which is aMainWindow) as parent to yourForm's constructor. If theFormconstructor correctly calls is superclassQObject(or whatever Qt class it's derived from), you can use (withinForm)qobject_cast<MainWindow*>(this->parent()). This is not a nice solution, though (still it works). One way to make this better is to change yourFormconstructor to take aMainWindow*as parent instead of anyQObject*/QWidget*. This would make sure that the cast will not fail. Even better would be that you then also directly store theMainWindow*as a member variable and use this instead ofparent(). The general scheme of this approach is: Use the constructor ofFormto hand down theMainWindowdirectly. Let theFormknow about itsMainWindow. This is the easiest way to access yourMainWindow. This eliminates the use ofMainWindow::Get()altogether. When you create yourFormobject you will always have the correctMainWindowat hand to pass it down.As others have mentioned, this is not the best approach as now
FormandMainWindoware highly coupled. Using signals and slots we can easily make everything work together perfectly.
Step 1: (I assume that in the end the tool button should be visually located within the Form.) Create the tool button inside the Form. Have a signalvoid Form::fit_to_window_button_pressed()and connect the tool buttonstriggered()signal with this new signal. Whenever you click on the tool button,Formwill emit a signal. (You can connect signals to signals.)
Step 2: When you create aForminMainWindowyou can connect the new signal fromFormwith whatever you like. Since you already haveactionFit_to_window(and it might be triggered in other ways as well) I suggest that to connect to its trigger slot:Form* temp = new Form(this); QObject::connect(temp, SIGNAL(fit_to_window_button_pressed()), this->actionFit_to_window, SLOT(trigger())); ... // and just like you have it already QObject::connect(this->actionFit_to_window, SIGNAL(triggered()), q, SLOT(fitSliceToBackground()));The order of the
connectstatements does not matter. Neither does it matter that all objects exist before you can do any of the connects. Only the objects which are used as sender and receiver in this particular connect statement need to be created by that time. Chaining signals and slots is a good way to decouple several classes in Qt. Nobody has to know much about the other. (Formdoes not know anything aboutMainWindowandMainWindowdoesn't care that you are using aQToolButtoninsideForm. You could easily change the tool button to something different later.)BTW, you should switch to the new connect syntax which will fail at compile time instead of at runtime:
QObject::connect(temp, &Form::fit_to_window_button_pressed, this->actionFit_to_window, &QAction::trigger); //and QObject::connect(this->actionFit_to_window, &QAction::triggered, q, &qMRMLSliceControllerWidget::fitSliceToBackground);