Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?



  • Hi All,

    I have made a custom widget. It is a QSplitter with a number of widgets in it. When I then place that custom widget into another QSplitter, I have to specify the parent, while I don't have to do that when I add a QTextBrowser. Why is this? How come a QTextBrowser automatically knows the parent, while my custom widget does not?

    Below are the relevant parts of the code:

    myHlayout = new QSplitter();
    rs232Rx = new RS232(myHlayout);
    rs232Tx = new RS232(myHlayout);
    myHlayout->setOrientation(Qt::Horizontal);
    myHlayout->addWidget(rs232Rx);
    myHlayout->addWidget(rs232Tx);
    

    class definition of RS232:

    class RS232 : public QWidget
    {
        Q_OBJECT
    public:
        RS232(QWidget *parent=0);
    public slots:
       <snip>
    signals:
       <snip>
       
    private:
       <snip>
    };
    

    Cheers,
    Cedric


  • Moderators

    @cdwijs said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    rs232Rx = new RS232(myHlayout);
    rs232Tx = new RS232(myHlayout);

    Why do you specify the parent here? Calling just addWidget() is enough.



  • @sierdzio said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    @cdwijs said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    rs232Rx = new RS232(myHlayout);
    rs232Tx = new RS232(myHlayout);

    Why do you specify the parent here? Calling just addWidget() is enough.

    Thanks Sierdzio, I have just tried it, but this line causes the widget to float in it's own window:
    rs232Rx = new RS232();

    This line causes the widget to correctly place itself in the QSplitter.
    rs232Rx = new RS232(myHlayout);

    Maybe this is only true on my PC:
    Windows 7 enterprise SP1
    QT 5.10.1
    mingw53_32

    Cheers,
    Cedric


  • Moderators

    @cdwijs said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    Thanks Sierdzio, I have just tried it, but this line causes the widget to float in it's own window:

    That's because your splitter needs a parent.

    myHlayout = new QSplitter();



  • @sierdzio said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    @cdwijs said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    Thanks Sierdzio, I have just tried it, but this line causes the widget to float in it's own window:

    That's because your splitter needs a parent.

    myHlayout = new QSplitter();

    I'm not convinced :-) This yields 3 floating windows:

        myVlayout = new QSplitter(parent);
        myVlayout->setOrientation(Qt::Vertical);
        myRxLabel = new QLabel("Rx");
        myTxLabel = new QLabel("Tx");
        myClearBtn = new QPushButton("Clear");
        myLog = new QPlainTextEdit();
        myHlayout = new QSplitter(myVlayout);
        myHlayout->setOrientation(Qt::Horizontal);
        myHlayout->addWidget(myRxLabel);
        rs232Rx = new RS232();
        myHlayout->addWidget(rs232Rx);
        myHlayout->addWidget(myTxLabel);
        rs232Tx = new RS232();
        myHlayout->addWidget(rs232Tx);
        myHlayout->addWidget(myClearBtn);
        myVlayout->addWidget(myLog);
        myVlayout->addWidget(myHlayout);
        myVlayout->show();
    

    This yields the desired effect:

     myRxLabel = new QLabel("Rx");
        myTxLabel = new QLabel("Tx");
        myClearBtn = new QPushButton("Clear");
        myLog = new QPlainTextEdit();
        myHlayout = new QSplitter();
        myHlayout->setOrientation(Qt::Horizontal);
        myHlayout->addWidget(myRxLabel);
        rs232Rx = new RS232(myHlayout);
        myHlayout->addWidget(rs232Rx);
        myHlayout->addWidget(myTxLabel);
        rs232Tx = new RS232(myHlayout);
        myHlayout->addWidget(rs232Tx);
        myVlayout = new QSplitter();
        myVlayout->setOrientation(Qt::Vertical);
        myHlayout->addWidget(myClearBtn);
        myVlayout->addWidget(myLog);
        myVlayout->addWidget(myHlayout);
        myVlayout->show();
    

    I noticed this yields the 2 RS232 widgets to be displayed before the Rx and Tx labels, and finally the clear button:

    myRxLabel = new QLabel("Rx");
        myTxLabel = new QLabel("Tx");
        myClearBtn = new QPushButton("Clear");
        myLog = new QPlainTextEdit();
        myHlayout = new QSplitter();
        myHlayout->setOrientation(Qt::Horizontal);
        rs232Rx = new RS232(myHlayout);
        rs232Tx = new RS232(myHlayout);
        myHlayout->addWidget(myRxLabel);
        myHlayout->addWidget(rs232Rx);
        myHlayout->addWidget(myTxLabel);
        myHlayout->addWidget(rs232Tx);
        myVlayout = new QSplitter();
        myVlayout->setOrientation(Qt::Vertical);
        myHlayout->addWidget(myClearBtn);
        myVlayout->addWidget(myLog);
        myVlayout->addWidget(myHlayout);
        myVlayout->show();
    

    Cheers,
    Cedric


  • Lifetime Qt Champion

    Hi,

    Can you show the RS232 constructor content ?



  • @SGaist
    Sure:

    RS232::RS232(QWidget *parent)
    {
        qDebug()<<Q_FUNC_INFO;
    #ifdef FAKE_MESSAGES
        myTimer = new QTimer();
        connect(myTimer,&QTimer::timeout,this,&RS232::slotTimer);
        myTimer->setInterval(500);
        myTimer->start();
    #endif
        mySettingsDia = new SettingsDialog;
        myRxQueue = new QQueue<unsigned char>;
        myRxQueue->clear();
    
        mySerialPort = new QSerialPort ;
        myTxTimer = new QTimer();
        myTxTimer->setSingleShot(true);
        myRxTimer = new QTimer();
        myRxTimer->setSingleShot(true);
    
        myLabel = new QLabel("COM-");
    
        mySettingsBtn = new QPushButton;
        mySettingsBtn->setIcon(QIcon(":/images/wrench.png"));
        mySettingsBtn->setToolTip("Settings");
    
        myConnectBtn = new QPushButton;
        myConnectBtn->setIcon(QIcon(":/images/disconnected.png"));
        myConnectBtn->setToolTip("Connect");
    
        const int LED_SIZE = 10;
        myRxLED = new LedIndicator();
        myRxLED->setLedSize(LED_SIZE);
        myRxLED->setOnColor(Qt::green);
        myRxLED->setToolTip("Rx");
    
        myTxLED = new LedIndicator();
        myTxLED->setLedSize(LED_SIZE);
        myTxLED->setOnColor(Qt::green);
        myTxLED->setToolTip("Tx");
    
        myHlayout = new QSplitter();
        myHlayout->setOrientation(Qt::Horizontal);
        myHlayout->addWidget(myLabel);
        myHlayout->addWidget(myTxLED);
        myHlayout->addWidget(myRxLED);
        myHlayout->addWidget(mySettingsBtn);
        myHlayout->addWidget(myConnectBtn);
    
        connect(mySettingsBtn,&QPushButton::clicked,this,&RS232::slotSettings);
        connect(myConnectBtn,&QPushButton::clicked,this,&RS232::slotConnect);
        connect(mySerialPort,&QSerialPort::readyRead,this,&RS232::slotRx);
        connect(myRxTimer,&QTimer::timeout,this,slotRxTimer);
        connect(myTxTimer,&QTimer::timeout,this,slotTxTimer);
        myHlayout->setParent(parent);
        myHlayout->show();
    }
    

    And the class:

    class RS232 : public QWidget
    {
        Q_OBJECT
    public:
        RS232(QWidget *parent=0);
    public slots:
        slotSettings(bool clicked);
        slotConnect(bool clicked);
        slotDisconnect(bool clicked);
        slotMessage(QString string);
        slotRx();
        slotRxTimer();
        slotTxTimer();
    #ifdef FAKE_MESSAGES
        slotTimer();
    #endif
    signals:
        void sigOpenChanged(bool open);
        void sigReceived(QString msg);
    private:
    #ifdef FAKE_MESSAGES
        QTimer *myTimer;
    #endif
        QTimer *myTxTimer;
        QTimer *myRxTimer;
        LedIndicator *myRxLED;
        LedIndicator *myTxLED;
        SettingsDialog *mySettingsDia;
        QSplitter *myHlayout;
        QLabel *myLabel;
        QPushButton *mySettingsBtn;
        QPushButton *myConnectBtn;
        SettingsDialog::Settings *mySerSettings;
        QSerialPort *mySerialPort;
        QQueue<unsigned char> *myRxQueue;
    };
    

  • Moderators

    @cdwijs said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    RS232::RS232(QWidget *parent)

    You are not initializing the parent class! Should be:

    RS232::RS232(QWidget *parent) : QWidget(parent)
    

    That should fix your problems. @SGaist well done :-)


  • Lifetime Qt Champion

    Also, you are using QSplitter like a layout manager which it is not. It's currently "floating" in RS232. Either put the splitter in a QVBox/HBoxLayout in RS232 (and other widgets you are using) or, depending on what you want to do, use layouts in place of QSplitter.



  • @SGaist said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    Also, you are using QSplitter like a layout manager which it is not. It's currently "floating" in RS232. Either put the splitter in a QVBox/HBoxLayout in RS232 (and other widgets you are using) or, depending on what you want to do, use layouts in place of QSplitter.

    I have made a new program that uses 3 layers (toplevel,midlevel,fourbuttons) of widgets:
    https://github.com/cdwijs/qt-experiments/tree/master/untitled2
    This works as expected, I see one window with groups of groups of buttons.

    Is this the correct way of doing things?

    Cheers,
    Cedric


  • Lifetime Qt Champion

    It depends, why do you need. Do you really have any use for all these QSplitter ?



  • @SGaist said in Parenting: why is a custom widget placed in a QSplitter not automatically a child of that splitter?:

    It depends, why do you need. Do you really have any use for all these QSplitter ?

    The splitters make sure I never have to alter the program if the end user wants to change some cosmetic aspect. I agree however that this program overuses Qsplitters.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.