Results 1 to 8 of 8

Thread: form.children() doesnt give all widgets for my dynamic form

  1. #1
    Join Date
    Mar 2012
    Location
    India
    Posts
    102
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default form.children() doesnt give all widgets for my dynamic form

    Hi,

    I am using QUiLoader. Following is my code:

    Qt Code:
    1. QUiLoader loader;
    2. QFile file(filename);
    3.  
    4. QWidget *form = loader.load(&file, this); //"this" here refers to the mainwindow class
    5.  
    6. int i;
    7. QObjectList list;
    8.  
    9. list = form->children();
    10. for(i = 0; i < list.size(); i++)
    11. {
    12. QString name = list.at(i)->objectName();
    13. qDebug() <<"object"<< i <<" = "<< name;
    14. }
    15.  
    16. file.close();
    To copy to clipboard, switch view to plain text mode 

    However the output only shows:

    object 0 = "_layout"
    object 1 = "qt_rubberband"
    object 2 = ""
    object 3 = "centralwidget"

    There are two custom widgets on this form which are being loaded (their constructor called) but their object names are not being listed. Is there something I am missing.


    -Charvi

  2. #2
    Join Date
    Mar 2012
    Location
    India
    Posts
    102
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: form.children() doesnt give all widgets for my dynamic form

    Somewhere I read "Qt Center is where all the questions related to QT get answered". But no answer yet ......

  3. #3
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: form.children() doesnt give all widgets for my dynamic form

    You are expecting an immediate response from a volunteer service: you do not get points for being impatient.

    Those four objects are the direct children of the widget you loaded. I'll guess the widgets you think are missing are children of "centralwidget". Perhaps you wanted QObject::findChildren().

  4. #4
    Join Date
    Mar 2012
    Location
    India
    Posts
    102
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: form.children() doesnt give all widgets for my dynamic form

    But QObject::findChildren() requires the object names of the widgets for creating references. This is not desirable for my dynamic loading.

    Now I have one more question. QUiLoader class must be creating the references to the widgets internally for creating them then y aren't they exposed for us to use. It must be using the DOM model for loading the form. The object names of the widgets are already present in the .ui file then why do I have to give them explicitly in findChildren() and findChild() methods. It should be read from the XML.

  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: form.children() doesnt give all widgets for my dynamic form

    QObject::findChildren() can find all children of a given type, it does not require a name as explained and demonstrated in the docs:
    Omitting the name argument causes all object names to be matched. The search is performed recursively.
    and
    This example returns all QPushButtons that are children of parentWidget:
    Qt Code:
    1. QList<QPushButton *> allPButtons = parentWidget.findChildren<QPushButton *>();
    To copy to clipboard, switch view to plain text mode 
    In your case you want all QWidgets.

  6. #6
    Join Date
    Mar 2012
    Location
    India
    Posts
    102
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: form.children() doesnt give all widgets for my dynamic form

    I have gone through this but this is not desirable in my case. I want to be able to reference the individual widgets by their object names so that it will be specific and want to follow the particular order in which they are on the form when I use getter functions to get the user input. But my other contradicting requirement is that my loader function has to be generic so that it can load any form which may be created well after the loader project is compiled and deployed.

    Also my other question
    Now I have one more question. QUiLoader class must be creating the references to the widgets internally for creating them then y aren't they exposed for us to use. It must be using the DOM model for loading the form. The object names of the widgets are already present in the .ui file then why do I have to give them explicitly in findChildren() and findChild() methods. It should be read from the XML.
    I understand the find() and findChildren() methods are for finding and creating references to widgets with the given object name from the form or for that matter all the widgets of a particular base class. But then the form.children() method should be able to display all the widgets on the form which is loaded through loader.load() (as in my code above) but that is not happening.
    Last edited by Charvi; 23rd May 2012 at 06:42.

  7. #7
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: form.children() doesnt give all widgets for my dynamic form

    Quote Originally Posted by Charvi View Post
    I have gone through this but this is not desirable in my case. I want to be able to reference the individual widgets by their object names
    Make up your mind. One moment you list all children, then actually want all descendants, then complain that findChildren() requires an object name, and when told it does not complain that you want to extract a widget by object name. If you know the object name then:
    Qt Code:
    1. QWidget *widget = form->findChildren<QWidget*>("someobjectname");
    To copy to clipboard, switch view to plain text mode 
    If you don't know the object names ahead of time then they should follow some useful pattern to allow you to pick them from the list of all descendent objects: then you know their names.
    so that it will be specific
    If an object of the name "someobjectname" name exists and it can be cast to a QWidget* (or QLineEdit* or whatever) then this pointer will specifically identify it.
    and want to follow the particular order in which they are on the form when I use getter functions to get the user input.
    That is what the form tab order, set in the Designer, is for. The order the focus moves "naturally" around the form is how the user might enter the data. It has no bearing on the order they actually enter the data or the order in which you can access the widget content.
    But my other contradicting requirement is that my loader function has to be generic so that it can load any form which may be created well after the loader project is compiled and deployed.
    There's no contradiction here. You are expecting a QMindReadingFormHandler class so you do not have to do the work. There is no such beast. The forms will have to follow some rules you define and your code will access them using those rules. For example, fields to be extracted might be named "fld_{seq}" and limited to text edits and check boxes: any other widget is ignored.

    I understand the find() and findChildren() methods are for finding and creating references to widgets with the given object name from the form or for that matter all the widgets of a particular base class. But then the form.children() method should be able to display all the widgets on the form which is loaded through loader.load() (as in my code above) but that is not happening.
    These two sentences are not connected. The first is (mostly) correct. The second is confused. Locating a single object using the generic findChildren() has nothing to do with displaying the dynamically loaded form. Your code above does nothing like displaying the form. If you want to do that you follow the simple pattern in the documentation for QUiLoader. Load the form and insert the resulting widget into the layout of your program.

    Here is a complete example. It will dump the content of any line edit on your form when you click Dump.
    Qt Code:
    1. #include <QtGui>
    2. #include <QUiLoader>
    3. #include <QDebug>
    4.  
    5. class MainWindow: public QMainWindow {
    6. Q_OBJECT
    7. public:
    8. MainWindow(const QString &fileName, QWidget *p = 0): QMainWindow(p), form(0) {
    9. QWidget *central = new QWidget(this);
    10. QVBoxLayout *layout = new QVBoxLayout(central);
    11. QPushButton *button = new QPushButton("Dump", central);
    12. layout->addWidget(button);
    13. central->setLayout(layout);
    14. setCentralWidget(central);
    15.  
    16. connect(button, SIGNAL(clicked()), SLOT(dump()));
    17.  
    18. QUiLoader loader;
    19. QFile file(fileName);
    20. if (file.open(QIODevice::ReadOnly)) {
    21. form = loader.load(&file, this);
    22. layout->insertWidget(0, form);
    23. file.close();
    24. }
    25. }
    26. private slots:
    27. void dump() {
    28. Q_ASSERT(form);
    29. // In "natural" order
    30. QList<QLineEdit*> edits = form->findChildren<QLineEdit*>();
    31. foreach(QLineEdit* edit, edits)
    32. qDebug() << edit->objectName() << edit->text();
    33.  
    34. // Alphabetical order of object name
    35. QMap<QString,QLineEdit*> map;
    36. foreach(QLineEdit* edit, edits)
    37. map.insert(edit->objectName(), edit);
    38. QMapIterator<QString,QLineEdit*> i(map);
    39. while (i.hasNext()) {
    40. i.next();
    41. qDebug() << i.key() << i.value()->text();
    42. }
    43. }
    44.  
    45. private:
    46. QWidget *form;
    47. };
    48.  
    49. int main(int argc, char *argv[])
    50. {
    51. QApplication app(argc, argv);
    52.  
    53. MainWindow m("test.ui");
    54. m.show();
    55. return app.exec();
    56. }
    57. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 

  8. #8
    Join Date
    Mar 2012
    Location
    India
    Posts
    102
    Thanks
    4
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11

    Default Re: form.children() doesnt give all widgets for my dynamic form

    Quote Originally Posted by ChrisW67 View Post
    Make up your mind. One moment you list all children, then actually want all descendants, then complain that findChildren() requires an object name, and when told it does not complain that you want to extract a widget by object name.
    Locating a single object using the generic findChildren() has nothing to do with displaying the dynamically loaded form. Your code above does nothing like displaying the form. If you want to do that you follow the simple pattern in the documentation for QUiLoader. Load the form and insert the resulting widget into the layout of your program.
    Ok. May be this is because I did not explain my requirement.

    First I wanted to create a generic loader program which will load any form. Till this I was done. I used the basic example in the QUiLoader example and did it.
    Now I want to take user input from this dynamically loaded form. (So if user types something into the line edit then take that input, etc.) But the QUiLoader class does not give direct access to the pointers of the widgets it creates while loading the form (these are private variables plus it doesnt store them.) We can create instances in our program by using object names which my function, as it is generic, wont have it. So first I get the object names, then the base classes of all widgets to create the references of to widgets.
    So I tried to get the object names as follows as u suggested:

    Qt Code:
    1. QList<QWidget *> list = form->findChildren<QWidget *>()
    2.  
    3. for(i = 0; i < list.size(); i++)
    4. {
    5. QString name = list.at(i)->objectName();
    6. qDebug() <<"object"<< i <<" = "<< qPrintable(name);
    7. }
    To copy to clipboard, switch view to plain text mode 

    It was good for many widgets. But for some widgets (I think the containers) it gives even the widgets inside them like follows:

    Qt Code:
    1. object 96 = textEdit
    2. object 97 = qt_scrollarea_viewport
    3. object 98 = qt_scrollarea_hcontainer
    4. object 99 =
    5. object 100 = qt_scrollarea_vcontainer
    6. object 101 =
    7. object 102 = plainTextEdit
    8. object 103 = qt_scrollarea_viewport
    9. object 104 = qt_scrollarea_hcontainer
    10. object 105 =
    11. object 106 = qt_scrollarea_vcontainer
    12. object 107 =
    13. object 108 = spinBox
    14. object 109 = qt_spinbox_lineedit
    15. object 110 = doubleSpinBox
    16. object 111 = qt_spinbox_lineedit
    17. object 112 = timeEdit
    18. object 113 = qt_spinbox_lineedit
    To copy to clipboard, switch view to plain text mode 

    This is a problem.
    Once I find a way out of this I can use widget.inherits("") to find the base class and then create the reference.

    That is what the form tab order, set in the Designer, is for. The order the focus moves "naturally" around the form is how the user might enter the data. It has no bearing on the order they actually enter the data or the order in which you can access the widget content.
    Also after taking the user input I want to send this to some other machine in form of packet. This is the sole reason I am worried about the order of widgets in the form because I will send the values in that order only. So no comples protocol needs to be established.

    You are expecting a QMindReadingFormHandler class so you do not have to do the work. There is no such beast.
    Well this is bad. Sorry if I annoyed you.


    Here is a complete example.
    Thank you very much for the code. It is useful.

Similar Threads

  1. Replies: 3
    Last Post: 30th April 2012, 07:39
  2. How to hide from taskbar a form showed form mainwindow
    By tonnot in forum Qt Programming
    Replies: 1
    Last Post: 10th February 2011, 14:36
  3. Dynamic form layout - Ability to add new rows
    By FaradayCage in forum Newbie
    Replies: 1
    Last Post: 22nd July 2010, 16:23
  4. Replies: 5
    Last Post: 12th March 2010, 21:43
  5. Hiding a form and opening another form
    By anafor2004 in forum Newbie
    Replies: 1
    Last Post: 20th February 2008, 15:04

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.