2016-06-19 42 views
2

我有一個類,它在QGridLayout中顯示帶有一些文本的QLabel。當QLabel是一個類成員時,一切正常,但當它不是時,它不會顯示在網格中。如果不是會員,則不顯示QLabel

QLabel不是成員,而是在構造函數中創建的。

class Account : public QWidget 
    { 
    private: 
     //QLabel lab; 
     QGridLayout * grid; 
      public: 
     Account(QWidget * parent=0); 

    public slots: 
     void spend(int); 
     void update(); 

    }; 

的.cpp

#include <QLabel> 
    #include <QLineEdit> 
    #include <QTextStream> 
#include <QFileInfo> 
#include <vector> 
#include <QGridLayout> 
#include <iostream> 

Account::Account(QWidget * parent) : QWidget(parent) 
{ 

    grid=new QGridLayout(this); 
    QLabel lab; 
    lab.setText("RFD"); 
    grid->addWidget(&lab,0,0); //is not displayed 
} 

QLabel是一個成員:

class Account : public QWidget 
    { 
    private: 
     QLabel lab; 
     QGridLayout * grid; 
      public: 
     Account(QWidget * parent=0); 

    public slots: 
     void spend(int); 
     void update(); 

    }; 

的.cpp

#include <QLabel> 
    #include <QLineEdit> 
    #include <QTextStream> 
    #include <QFileInfo> 
    #include <vector> 
    #include <QGridLayout> 
    #include <iostream> 

    Account::Account(QWidget * parent) : QWidget(parent) 
    { 

     grid=new QGridLayout(this); 
     lab.setText("RFD"); 
     grid->addWidget(&lab,0,0); //is displayed 
    } 

爲什麼會這樣?

+1

如果您在堆棧上創建實驗室,它會在塊的末端立即被破壞(即ctor的末端)。您必須在堆上創建它並/或使其成爲會員 –

回答

3

因爲當你在你的構造函數聲明QLabel它只是一個局部變量,因此在功能的端部落外的範圍(見下文我的意見):

{ 
    grid=new QGridLayout(this); 
    QLabel lab; // created here 
    lab.setText("RFD"); 
    grid->addWidget(&lab,0,0); //is not displayed 
} // destroyed here as the variable is out of scope 

如果你想在你的構造函數中創建它,那麼將它作爲一個指針並將它新增 - 你仍然需要跟蹤這個指針,無論是作爲成員變量還是傳遞指向其他函數/類的指針照顧它...(即,當你完成它時刪除它...

而且 - addWidget()需要一個指針,所以它可能會處理它本身的破壞 - 因此你也許可以這樣做:

{ 
    grid=new QGridLayout(this); 
    QLabel *pLab = new QLabel(this); 
    lab.setText("RFD"); 
    grid->addWidget(pLab,0,0); //is not displayed 
} 
+0

謝謝! 'grid = new QGridLayout(this);' 'QLabel * lab = new QLabel;' 'lab-> setText(「RFD」);' 'grid-> addWidget(lab,0,0);' works 。但是我曾經聽說過Qt會自己處理堆內存,不是嗎?或者在這種情況下,'* lab'指針將被刪除,但其堆內存將保持不變? – parsecer

+2

是的,我相信你是正確的,Qt會照顧它...但它總是感覺像一個漏洞 - 從我的純C++背景:o –

+1

@parsecer:如果你給QLabel一個父項,就像在'新的QLabel(this)',如果'this'被銷燬,Qt會爲你清理它。如果你需要明確地做到這一點,請參閱https://doc.qt.io/qt-5/qobject.html#setParent。 – Bugfinger

1

QLabel lab;是住一個局部變量,直到函數的末尾,然後自動銷燬,所以當你想顯示它時,你想要顯示的標籤實際上不再存在了。

而且Qt擁有一個非常規memory model要求您newQLabel,然後傳遞一個擁有原始指針到Qt的自動delete後,當父被刪除的功能。 如果你使用delete它手動獲得一個通常導致崩潰的雙重delete(一個來自你和一個來自Qt)。手動delete對象將自動將其從父項分離,因此您不會得到雙重delete

Qt的希望您能做到這一點是

QLabel *lab = new QLabel; 
lab->setText("RFD"); 
grid->addWidget(lab,0,0); 

雖然這看起來像一個內存泄漏的方式,它不是,因爲Qt的內存模型。

+0

謝謝你的回答。 – parsecer

+0

這並非完全正確。正如您提供的鏈接所述,當您在父對象之前自己刪除對象時,您將不會得到雙重刪除。當對象被銷燬時,它們將從父對象中移除。當您嘗試在父母已經銷燬後自行刪除某些內容時,您只會收到雙重刪除。它也不會強制你使用'new'。如果你不使用'new',你只需要處理定義順序。但除此之外,你的回答是正確的。 – thuga

+0

@thuga你可以進入更多的細節? Qt無法知道某個對象是否已被您刪除。你可以*從Qt取回所有權,然後手動刪除。你也可以給Qt一個不是由'new'創建的指針,並在父類消失之前取回所有權,不確定它是否可維護。 – nwp

相關問題