2010-04-06 14 views
7

Ho scritto un piccolo programma per testare l'accesso allo slot di un genitore del widget. Fondamentalmente, ha due classi:Qt - Chiamare gli slot del genitore del widget

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

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

nella funzione principale, ho semplicemente creato un'istanza di Widget, e chiamato show() su di essa . Questa istanza Widget ha un'etichetta, una QString, un'istanza della classe customWidget e due pulsanti (all'interno della classe ui, pushButton e pb). Uno dei pulsanti chiama uno slot nella sua classe chiamata changeLabel(), che, come suggerisce il nome, cambia l'etichetta in qualunque cosa sia impostata nella QString in essa contenuta. L'ho fatto solo per verificare che changeLabel() funzionasse. Questo pulsante funziona correttamente. L'altro pulsante chiama uno slot nell'istanza customWidget, chiamata callParentSlot(), che a sua volta tenta di chiamare lo slot changeLabel() nel suo genitore. Dato che in questo caso so che il suo genitore è in realtà un'istanza di Widget, lancio il valore di ritorno di parentWidget() su Widget *. Questo pulsante arresta il programma. Ho creato un pulsante all'interno di customWidget per tentare di chiamare anche lo slot gen di customWidget, ma anche il programma si blocca. Ho seguito la domanda this. Cosa mi manca?

+0

Perché stai cercando di chiamare lo slot del genitore? Dato che è già uno slot, perché non emetti un segnale dal bambino e connetti questo segnale allo slot del genitore? – erelender

+0

È perché voglio aggiornare alcune variabili nel widget padre ogni volta che apporto alcune modifiche nel widget figlio. Non riuscivo a capire in nessun altro modo che avere il bambino chiama lo slot del widget dei suoi genitori. –

+0

Il problema è che le modifiche nel widget figlio a cui sono interessato sono attivate dai pulsanti nel widget figlio, quindi devo trovare un modo per aggiornare le variabili presenti nel widget padre all'interno del widget figlio. –

risposta

2

Non si imposta mai il widget genitore per l'istanza customWidget. Pertanto, è probabile che this->parentWidget() restituisca un puntatore NULL. Apportare le modifiche seguenti:

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

Vorrei anche consigliare utilizzando un dynamic_cast e controllando il valore restituito. Ciò ha impedito il crash in entrambi i casi in cui il genitore è NULL e dove il genitore non è della classe corretta.

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

altro approccio sarebbe chiamare slot parente tramite l'interfaccia segnali e slot. Collega il nuovo segnale personalizzatoWidget allo slot Widget nel costruttore Widget. Quindi puoi chiamare lo slot da customWidget come segue.

emit callParentSignal(); 
+0

Si blocca ancora, anche dopo aver impostato esplicitamente il suo genitore. Il genitore di cwidget non dovrebbe essere impostato automaticamente quando viene chiamato addWidget (cwidget)? –

+0

So che non è una buona idea, ma sono bloccato a fare questo o dover riscrivere un'enorme porzione di codice da un'app con cui sto lavorando con –

+0

Non sono sicuro se aggiungerlo a tale problema. Anche così, sei sicuro che usi il widget corretto come genitore? –

Problemi correlati