[SOLVED] Signals and Slots beginner problem



  • Hi all

    i'm currently busy with a C++/QT course and battling a bit with some of the concepts moving from basic C++ to QT.
    at the moment i'm busy with an assignment where I have to write a gui application to calculate BMI. I managed to complete the gui but i'm struggling a bit with the signals and slots.

    my code:

    bmiGui.h

    @
    #ifndef BMIGUI_H
    #define BMIGUI_H
    #include <QWidget>
    #include <QDoubleSpinBox>
    #include <QRadioButton>
    #include <QLineEdit>
    #include <QPushButton>
    #include <QLabel>

    class bmiGui : public QWidget
    {
    public:
    bmiGui();
    private:
    QDoubleSpinBox* m_weight;
    QDoubleSpinBox* m_height;
    QRadioButton* m_kilograms;
    QRadioButton* m_pounds;
    QRadioButton* m_meters;
    QRadioButton* m_centimeters;
    QPushButton* m_calculate;
    QPushButton* m_bmiInfo;
    QPushButton* m_clear;
    QLineEdit* m_bmi;
    QLabel* m_weightlbl;
    QLabel* m_heightlbl;
    QLabel* m_bmilbl;

    };

    #endif // BMIGUI_H
    @

    bmiGui.cpp
    @
    #include "bmiGui.h"
    #include <QWidget>
    #include <QTextEdit>
    #include <QLabel>
    #include <QPushButton>
    #include <QBoxLayout>
    #include <QTextEdit>
    #include <QLabel>
    #include <QLineEdit>
    #include <QRadioButton>
    #include <QDoubleSpinbox>
    #include <QButtonGroup>
    #include <QFormLayout>
    bmiGui::bmiGui() {
    m_weight = new QDoubleSpinBox;
    m_height = new QDoubleSpinBox();
    m_kilograms = new QRadioButton("Kilograms");
    m_pounds = new QRadioButton("Pounds");
    m_meters = new QRadioButton("Meters");
    m_centimeters = new QRadioButton("Centimeters");
    m_calculate = new QPushButton("Calculate");
    m_bmiInfo = new QPushButton("BMI Information");
    m_clear = new QPushButton;
    m_bmi = new QLineEdit;
    m_weightlbl = new QLabel("Enter Weight");
    m_heightlbl = new QLabel("Enter Height");
    m_bmilbl = new QLabel("BMI");
    QButtonGroup* weightUnits = new QButtonGroup;
    QButtonGroup* heightUnits = new QButtonGroup;
    weightUnits->addButton(m_kilograms);
    weightUnits->addButton(m_pounds);
    heightUnits->addButton(m_meters);
    heightUnits->addButton(m_centimeters);

    QVBoxLayout* col1 = new QVBoxLayout;
    col1->addWidget(m_weightlbl);
    col1->addWidget(m_heightlbl);
    col1->addWidget(m_bmilbl);
    
    QVBoxLayout* col2 = new QVBoxLayout;
    col2->addWidget(m_weight);
    col2->addWidget(m_height);
    
    
    QVBoxLayout* col3 = new QVBoxLayout;
    col3->addWidget(m_kilograms);
    col3->addWidget(m_meters);
    
    
    
    QVBoxLayout* col4 = new QVBoxLayout;
    col4->addWidget(m_pounds);
    col4->addWidget(m_centimeters);
    
    
    
    QHBoxLayout* box = new QHBoxLayout;
    box->addLayout(col1);
    box->addLayout(col2);
    box->addLayout(col3);
    box->addLayout(col4);
    
    QHBoxLayout* cbtnRow = new QHBoxLayout;
    cbtnRow->addWidget(m_calculate);
    
    QHBoxLayout* btmRow = new QHBoxLayout;
    btmRow->addWidget(m_bmilbl);
    btmRow->addWidget(m_bmi);
    btmRow->addWidget(m_bmiInfo);
    

    QVBoxLayout* box2 = new QVBoxLayout;
    box2->addLayout(box);
    box2->addLayout(cbtnRow);
    box2->addLayout(btmRow);

    setLayout(box2);
    

    }

    QObject::connect(m_calculate, SIGNAL(clicked()), bmi, SLOT(calcBmi(m_weight, m_height));
    @

    I connected the calculate button with the calcBmi slot from another class called bmi. How could I pass the values in the weight and height QdoubleSpinBoxes to the calcBmi slot? also if the calcBmi slot/function calculated the bmi how could I send the bmi value to the bmi QLineEdit in the bmiGui class? As far as I understand all the bmiGui widgets are private member variables of bmiGui so the bmi class doesn't have access to them?
    Thanks in advance
    Deon

    [edi: please add @tags before and after your code for readability, Eddy]


  • Lifetime Qt Champion

    Hi,

    You can't pass value like that.

    The most straight forward way to do it is have a slot in bmi that is parameterless and call calBmi from it.

    If you want to update the value in a widget inside bmi from the outside, just add a setter for it (e.g. a slot) that will update the correct widget.

    Hope it helps


  • Moderators

    Also, don't forget Q_OBJECT in your class.


  • Lifetime Qt Champion

    And re-run qmake before building once you've added Q_OBJECT



  • So if I add a void calculate slot in the bmi class that calls calcBmi how would calcBmi be able to get the m_weight and m_height widget values?

    So to set the BMI QLineEdit I would add a setBMI slot in the bmiGui class?


  • Lifetime Qt Champion

    Before analyzing further, can you show where

    @QObject::connect(m_calculate, SIGNAL(clicked()), bmi, SLOT(calcBmi(m_weight, m_height));@

    is ?



  • I think I know how to do it now but ran into another problem.
    I created a slot in the bmiGui class which then calls the calcBmi function of the bmi class.
    I have 2 QDoubleSpinBoxes in bmiGui for weight and height. How could I read they're values into
    2 variables for weight and height to pass to the calcBmi function of the bmi class?

    The way i tried it:

    double weight = m_weight.value();
    double height = m_height.value();

    I keep getting an error "request for member 'value' ((bmiGui*)this->bmiGui::m_weight', which is of non class type QDoubleSpinBox*"



  • use
    @
    m_weight->value();
    @
    The terrible error message is telling you that you are using a "." on a pointer.



  • Just a rough code..
    [quote author="Dn588" date="1396377011"]
    QObject::connect(m_calculate, SIGNAL(clicked()), bmi, SLOT(calcBmi(m_weight, m_height));
    [/quote]

    This is wrong way,You cannot connect in such way.

    [quote author="Dn588" date="1396377011"]
    I connected the calculate button with the calcBmi slot from another class called bmi. How could I pass the values in the weight and height QdoubleSpinBoxes to the calcBmi slot?also if the calcBmi slot/function calculated the bmi how could I send the bmi value to the bmi QLineEdit in the bmiGui class? [/quote]

    Do not make slot in bmi class.make a simple calcbmi() function in bmi class.
    e.g;
    QObject::connect(m_calculate, SIGNAL(clicked()), this, SLOT(BtnClicked()));

    void bmiGui::BtnClicked()
    {
    bmi obj; //make an object of bmi class
    double weight = m_weight.value();
    double height = m_height.value();
    double result = obj.calcBmi(weight,height); //calcBmi function in bmi class that returns value after calculating
    m_bmi.setText(QString::number(result));
    }

    [quote author="Dn588" date="1396377011"]
    As far as I understand all the bmiGui widgets are private member variables of bmiGui so the bmi class doesn't have access to them? [/quote]

    No this is not the reason, you are not passing gui you dealing with values.
    hope it helps.



  • Thanks ScotR and IamSumit I won't forget that in future:)

    My calculate_clicked slot now looks like this:

    @
    {
    bmi obj;
    weight = m_weight->value();
    height = m_height->value();
    retVal = obj.calcBmi(weight, height);
    bmi.setText(bmiVal);
    }
    @

    Now i'm getting an error "No matching function bmi::bmi() candidates are bmi::bmi(double double) and bmi::bmi(const bmi&)
    but when I instantiate bmiObj I pass weight and height as parameters which are both of type double.
    Any idea what I am doing wrong?

    [edit: added coding tags SGaist]



  • [quote author="Dn588" date="1396455117"]

    Any idea what I am doing wrong?[/quote]

    1. You are forgetting to put your code inside of "@" signs.

    2. I don't know what the line
      @
      bmi obj;
      @

    does. You haven't shown the definition of the type "bmi".



  • Hi ScottR Sorry I completely forgot about code formatting...

    My bmi class looks like this:

    @

    bmi.h

    #ifndef BMI_H
    #define BMI_H

    class bmi
    {
    public:
    bmi(double weight, double height);
    double calcBmi(double weight, double height);
    private:
    double m_weight, m_height;
    };

    #endif // BMI_H

    bmi.cpp

    #include "bmi.h"

    bmi::bmi(double weight, double height) : m_weight(weight), m_height(height)
    {

    }

    double bmi::calcBmi(doubleweight, double height) {
    return weight / (height * height);
    }
    @



  • You want to use
    @
    bmi obj(weight, height);
    @

    I can't tell where you will get weight and height from.

    I think you may be confused between the bmiGui class and the bmi class?



  • You have two choice either pass the values in constructor or in function(as i gave you code)
    [quote author="Dn588" date="1396468975"]Hi ScottR Sorry I completely forgot about code formatting...

    My bmi class looks like this:

    @

    bmi.h

    #ifndef BMI_H
    #define BMI_H

    class bmi
    {
    public:
    bmi(double weight, double height);
    double calcBmi(double weight, double height);
    private:
    double m_weight, m_height;
    };

    #endif // BMI_H

    bmi.cpp

    #include "bmi.h"

    bmi::bmi(double weight, double height) : m_weight(weight), m_height(height)
    {

    }

    double bmi::calcBmi(doubleweight, double height) {
    return weight / (height * height);
    }
    @[/quote]

    Here you should use a simple constructor without parameter.
    e.g;
    instead of
    bmi(double weight, double height); write bmi(); only
    edit your code in both .h and .cpp file for simple parameterless constructor.

    hope it helps



  • Thanks That worked:) Now i'm getting a few error messages saying undefined reference to 'vtable for bmiGui' any idea what that means?



  • This most probably means that your moc file is not up to date. Try to clean the project, run qmake and build again.

    And be sure that your classes using signal and slots have the Q_OBJECT macro (before running qmake).

    Edit: it may also be caused by a forgotten dependance in your .pro file. Could you give a more detailed compiler output?



  • Thanks a lot it's working Perfectly now!.

    One more thing i'm struggling to find,
    when creating a layout is there any member function of QRadioButton to set a radioButton as checked by default when the program starts?



  • HI ..
    Yes .Use
    void setChecked(bool)
    member function.
    Hope it helps



  • Thanks IamSumit that worked:)


  • Moderators

    Hi,
    Could you please edit your first post and prepend [solved] to it. That way others can see easily it's solved. Thanks.


Log in to reply
 

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