Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Custom Class findChild<QPushButton *>(); Not Finding Child



  • QPushButton *numButtons[15];
        for(int i = 0; i<11; i++){
            QString buttonName = "Button" + QString::number(i);
            numButtons[i] = makeCallDialog::findChild<QPushButton *>(buttonName);
            qDebug() << "Button: " << numButtons[i];
            qDebug() << buttonName;
            connect(numButtons[i], &QPushButton::released, this, &makeCallDialog::numPressed);
        }
    

    I have 10 QPushButtons (Button0, Button1, ..., Button9). I am trying to connect them via this for() loop, but Connect() returns with invalid null parameter. I have determined that the findChild<...> code isn't finding the element/ child. Why would this happen?

    makeCallDialog is my class name. Also, I am not using the Designer to create the UI.


  • Lifetime Qt Champion

    Hi
    Should that not be
    makeCallDialog->findChild<QPushButton *>(buttonName);
    as FindChild is not static ?

    also, you did call
    pushButton0->setObjectName("Button0");
    etc..
    when you created them ?
    The Text on button is not their name.



  • @mrjj

    When I change it to your suggestion I get the error: 'makeCallDialog' does not refer to a value

    But I did not setObjectName. Making this change solve my problem. Thank you!

    How is the object name different from the variable name? I assumed that whatever I name a variable is its object name.


  • Lifetime Qt Champion

    @Burke212 said in Custom Class findChild<QPushButton *>(); Not Finding Child:

    How is the object name different from the variable name? I assumed that whatever I name a variable is its object name.

    Hi
    the variable name is a local thing you use to store a pointer to the object in.
    FindChild has no way of knowing such names.
    The objectName however, is a property of the object, much like its size and color and
    Qt/FindChild know of this pr design.
    And just like its size, its part of the object. The variable name , you use is not part of the object and
    therefore not related to the variable name at all.



  • @Burke212

    Hi,

    I think the easiest way would be, if you use an iterator to go through your QList of QPushButtons and connect the current QPushButton while iterating. You can also rename your Buttons during this process.

    EDIT: Where do you create your Buttons?

    QPushButton *num[10];
    

    Does not create an array of 10 (usable) PushButton-Objects. You define 10 pointers to a QPushButton there, but no QPushButton is initialized.
    Better:

    QPushButton myBtn; // Calls Std-Constructor of QPushButton
    // OR
    QPushButton *myBtn = new QPushButton ();
    

    I dont get the use of findChild there... If you are trying to "find" the buttons, that were created somewhere else (in parent class), to connect them, why dont you connect them directly in your parent class? (something like sending a signal to notify your Dialog that "Button Nr. X" was pressed / released)



  • @Burke212

    makeCallDialog is a Class Name, not an object. When you call findChild function, you need an object. like that:

    makeCallDialog dlg;
    dlg.findChild();

    makeCallDialog *pDlg = new makeCallDialog();
    pDlg->findChild();



  • @Pl45m4

    I don't have a QList of QPushButtons, I simply declare the buttons in the header, then define them in cpp.

    In header:

    QPushButton *Button0;
    ...
    QPushButton *Button9;
    

    In cpp:

    Button0 = new QPushButton(this);
    ....
    Button9 = new QPushButton(this);
    

    The *QPushButton num[10] is going to store the button's names & connect them to numPressed().

    numButtons[i] = makeCallDialog::findChild<QPushButton *>(buttonName);
    
    connect(numButtons[i], &QPushButton::released, this, &makeCallDialog::numPressed);
    

    So the idea is numButtons[0] is set to Button0, then Button0 is connected to numPressed(), and so forth with the other elements in the array.


  • Qt Champions 2019

    @Burke212 Why do you need all these Button0..Button9 variables if you're then storing the pointers in numButtons?
    Why not simply

    numButtons[i] = new QPushButton(this);
    

    ?



  • @Burke212 Just some side notes from my side.
    It is not common do define a class name with starts with lowcase. A good pratice is to have class names calmelcase starting with upper case (makeCallDialog should by MakeCallDialog) and variable name starting with low case.

    Second: why do you use sereval variables and not a container like QVector

    in header

    QVector<QPushButton*> myButtons;
    

    in cpp:

    ...
        for(int idx = 0; idx < 10; ++idx)
        {
            myButtons << new QPushButton(this);
            connect(myButtons.last(), &QPushButton::released, this, &makeCallDialog::numPressed);
        }
    ...
    


  • @jsulm

    I'm following this tutorial. Since I'm working in source only, I'm not able to reference from the UI. So that's where my issue came from; in the tutorial he references the buttons because they're in the UI/ designer.



  • @Burke212 this works in tutorial, because QPushButton instance are defined with .ui and eah one has a name
    0_1551192414591_08828eee-fb13-493c-81b6-450fba0fe5d8-image.png

    "Button0" to "Button9", this has no link with variable name.

    To made this work, you must do:

    Button0 = new QPushButton(this);
    Button0->setObjectName("Button0");
    ....
    Button9 = new QPushButton(this);
    Button9->setObjectName("Button9");
    

    or

    ...
        for(int idx = 0; idx < 10; ++idx)
        {
            myButtons << new QPushButton(this);
            myButtons.last()->setObjectName(QStringLiteral("Button%1").arg(idx));
            connect(myButtons.last(), &QPushButton::released, this, &makeCallDialog::numPressed);
        }
    ...
    


  • Thank you, everyone for your awesome help!



  • @Burke212

    One more thing... :)
    So you create 10 Buttons and connect them somehow to "numPressed", that prints or computes the button-number, if a button is clicked + released, right?

    The use of a QButtonGroup would make this even easier.
    https://doc.qt.io/qt-5.6/qbuttongroup.html

    Add your buttons to your buttonGroup and setID of each button.
    ButtonGroup also provides signals and functions to work with. Maybe your own connection is not necessary anymore and you dont need to rename every single button, because you can work with the groupID.

    When adding the buttons to your group, set your own IDs, as the default buttonID in a buttonGroup starts at -2 and decreases with every additional button (this gave me headache in one of my projects some time ago... Of course, I didnt set my own IDs and was expecting the ID to start at 0 increasing. And of course I didnt read the Docs of the addButton-Function back then) :)