Solved 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 -
@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_32Cheers,
Cedric -
@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 -
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; };
-
@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 :-)
-
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 -
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.