I wrote a small program to test accessing a widget parent's slot. Basically, it has two classes:
Widget:
namespace Ui
{
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
QLabel *newlabel;
QString foo;
public slots:
void changeLabel();
private:
Ui::Widget *ui;
};
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
customWidget *cwidget = new customWidget();
newlabel = new QLabel("text");
foo = "hello world";
this->ui->formLayout->addWidget(newlabel);
this->ui->formLayout->addWidget(cwidget);
connect(this->ui->pushButton,SIGNAL(clicked()),cwidget,SLOT(callParentSlot()));
connect(this->ui->pb,SIGNAL(clicked()),this,SLOT(changeLabel()));
}
void Widget::changeLabel(){
newlabel->setText(this->foo);
}
and customWidget:
class customWidget : public QWidget
{
Q_OBJECT
public:
customWidget();
QPushButton *customPB;
public slots:
void callParentSlot();
};
customWidget::customWidget()
{
customPB = new QPushButton("customPB");
QHBoxLayout *hboxl = new QHBoxLayout();
hboxl->addWidget(customPB);
this->setLayout(hboxl);
connect(this->customPB,SIGNAL(clicked()),this,SLOT(callParentSlot()));
}
void customWidget::callParentSlot(){
((Widget*)this->parentWidget())->changeLabel();
}
in the main function, I simply created an instance of Widget, and called show() on it. This Widget instance has a label, a QString, an instance of customWidget class, and two buttons (inside the ui class, pushButton and pb). One of the buttons calls a slot in its own class called changeLabel(), that, as the name suggests, changes the label to whatever is set in the QString contained in it. I made that just to check that changeLabel() worked. This button is working fine. The other button calls a slot in the customWidget instance, named callParentSlot(), that in turn tries to call the changeLabel() slot in its parent. Since in this case I know that its parent is in fact an instance of Widget, I cast the return value of parentWidget() to Widget*. This button crashes the program. I made a button within customWidget to try to call customWidget's parent slot as well, but it also crashes the program. I followed what was on this question. What am I missing?
You never set the parent widget for your customWidget
instance. So, this->parentWidget()
is likely returning a NULL pointer. Make the following changes:
customWidget *cwidget = new customWidget(this);
...
customWidget(QWidget *parent);
...
customWidget::customWidget(QWidget *parent) : QWidget(parent)
I would also advise using a dynamic_cast and checking the return value. This went prevent your crash in both the case where parent is NULL and where parent is not of the correct class.
void customWidget::callParentSlot()
{
Widget *w = dynamic_cast<Widget *> (this->parentWidget());
if (0 != w)
w->changeLabel();
/* else handle the error */
}
Another approach would be to call the parent slot through the signals and slots interface. Connect the new customWidget signal to the Widget slot in the Widget constructor. Then you can call the slot from customWidget as follows.
emit callParentSignal();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With