Qt-вызов родительских слотов виджета
Я написал небольшую программу для тестирования доступа к родительскому слоту виджета. В основном, он имеет два класса:
Виджет:
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);
}
И 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();
}
В основной функции я просто создал экземпляр виджета и вызвал show () на нем. Этот экземпляр виджета имеет метку, в QString, а экземпляр класса customWidget, и две кнопки (внутри класса пользовательского интерфейса, кнопки и ПБ). Одна из кнопок вызывает слот в своем собственном классе под названием changeLabel (), который в качестве имени предлагает, изменяет метку на то, что установлено в QString, содержащемся в нем. Я сделал это только для того, чтобы проверить, что changeLabel() работает. Эта кнопка работает нормально. Другая кнопка вызывает слот в экземпляре customWidget с именем callParentSlot (), который в свою очередь пытается вызвать слот changeLabel () в своем родителе. Поскольку в этом случае я знаю, что его родитель на самом деле является экземпляром Widget, я приведу возвращаемое значение parentWidget() к Widget*. Эта кнопка завершает работу программы. Я сделал кнопку в customWidget, чтобы попытаться вызвать Родительский слот customWidget, а также, но он также аварийно завершает работу программы. Я следил за тем, что было на этом вопросе. Чего мне не хватает?
1 ответ:
Вы никогда не устанавливаете Родительский виджет для вашего экземпляра
customWidget
. Таким образом,this->parentWidget()
, скорее всего, возвращает нулевой указатель. Внесите следующие изменения:customWidget *cwidget = new customWidget(this); ... customWidget(QWidget *parent); ... customWidget::customWidget(QWidget *parent) : QWidget(parent)
Я бы также посоветовал использовать dynamic_cast и проверять возвращаемое значение. Это предотвратит ваш сбой как в случае, когда parent равен NULL, так и в случае, когда parent не относится к правильному классу.
Другой подход заключается в вызове родительского слота через интерфейс сигналов и слотов. Подключите новый сигнал customWidget к Слот виджета в конструкторе виджетов. Затем вы можете вызвать слот из customWidget следующим образом.void customWidget::callParentSlot() { Widget *w = dynamic_cast<Widget *> (this->parentWidget()); if (0 != w) w->changeLabel(); /* else handle the error */ }
emit callParentSignal();