Qt - Вызов слотов родителя виджета - PullRequest
7 голосов
/ 06 апреля 2010

Я написал небольшую программу для проверки доступа к слоту родителя виджета. По сути, у него есть два класса:

Виджет:

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();
}

в основной функции я просто создал экземпляр Widget и вызвал для него show (). Этот экземпляр Widget имеет метку, QString, экземпляр класса customWidget и две кнопки (внутри класса пользовательского интерфейса, pushButton и pb). Одна из кнопок вызывает слот в своем собственном классе с именем changeLabel (), который, как следует из названия, меняет метку на то, что установлено в QString, содержащейся в нем. Я сделал это только для того, чтобы проверить, что changeLabel () работает. Эта кнопка работает нормально. Другая кнопка вызывает слот в экземпляре customWidget с именем callParentSlot (), который, в свою очередь, пытается вызвать слот changeLabel () у своего родителя. Поскольку в этом случае я знаю, что его родитель на самом деле является экземпляром Widget, я приведу возвращаемое значение parentWidget () к Widget *. Эта кнопка вылетает из программы. Я сделал кнопку в customWidget, чтобы попытаться вызвать родительский слот customWidget, но это также приводит к сбою программы. Я следил за тем, что было на этом вопросе. Чего мне не хватает?

1 Ответ

2 голосов
/ 06 апреля 2010

Вы никогда не устанавливаете родительский виджет для своего экземпляра customWidget. Таким образом, this->parentWidget(), вероятно, возвращает нулевой указатель. Сделайте следующие изменения:

customWidget *cwidget = new customWidget(this);
...
customWidget(QWidget *parent);
...
customWidget::customWidget(QWidget *parent) : QWidget(parent)

Я бы также посоветовал использовать dynamic_cast и проверить возвращаемое значение. Это предотвратило ваш сбой как в случае, когда parent имеет значение NULL, так и в том случае, если parent не соответствует нужному классу.

void customWidget::callParentSlot()
{
    Widget *w = dynamic_cast<Widget *> (this->parentWidget());
    if (0 != w)
        w->changeLabel();
    /* else handle the error */
}

Другой подход заключается в вызове родительского слота через интерфейс сигналов и слотов. Подключите новый сигнал customWidget к слоту Widget в конструкторе Widget. Затем вы можете вызвать слот из customWidget следующим образом.

emit callParentSignal();
...