2010-04-06 101 views
7

我寫了一個小程序來測試訪問窗口窗口小部件的窗口。基本上,它有兩類:Qt - 調用窗口小部件父窗口

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

和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實例,並稱之爲表演( 。這個Widget實例有一個標籤,一個QString,一個customWidget類的實例和兩個按鈕(在ui類中,pushButton和pb)。其中一個按鈕在其自己的類中調用了一個名爲changeLabel()的槽,如名稱所示,它將標籤更改爲包含在其中的QString中設置的任何值。我只是爲了檢查changeLabel()的工作。這個按鈕工作正常。另一個按鈕調用名爲callParentSlot()的customWidget實例中的插槽,該插槽又會嘗試調用其父級中的changeLabel()插槽。因爲在這種情況下,我知道它的父實際上是一個Widget的實例,所以我將parentWidget()的返回值轉換爲Widget *。該按鈕會使程序崩潰。我在customWidget中創建了一個按鈕,以嘗試調用customWidget的父插槽,但它也會使程序崩潰。我跟着this的問題。我錯過了什麼?

+0

你爲什麼要打電話給父母的插槽?由於它已經是一個插槽,爲什麼不從孩子發出信號並將此信號連接到父母的插槽? – erelender 2010-04-06 13:15:29

+0

這是因爲我想每次在子部件中進行一些更改時,都要更新父部件中的一些變量。除了讓孩子打電話給父母小工具的插槽之外,我無法想出任何其他方式。 – 2010-04-06 13:18:12

+0

問題是,我關心的子窗口小部件中的更改是由子窗口小部件中的按鈕觸發的,所以我需要找出一種方法來更新子窗口小部件中父控件上的變量。 – 2010-04-06 13:25:29

回答

2

您從未爲您的customWidget實例設置父窗口小部件。所以,this->parentWidget()可能會返回一個NULL指針。進行以下更改:

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

我還建議使用dynamic_cast並檢查返回值。這樣做可以防止在父類爲NULL且父類不是正確類的情況下發生崩潰。

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(); 
+0

即使在明確設置其父項之後,它仍然崩潰。在調用addWidget(cwidget)時,不應該自動設置cwidget的父級? – 2010-04-06 13:07:26

+0

我知道這不是一個好主意,但我堅持要做到這一點,或者不得不從我正在使用的應用程序重寫一大段代碼 – 2010-04-06 13:10:25

+0

我不確定addWidget是否能夠補救它。即便如此,你確定它使用正確的小部件作爲父項嗎? – 2010-04-06 13:12:44

相關問題