c++qtqt5qt5.5

Qt connect(*sender, *signal, *receiver, *method) doesn't call slots


I'm very new to Qt and also to c++. I tried to do a little Celsius/Fahrenheit converter. On the UI I use QDial and QLCDNumber to respectively change and show the temperature. Unfortunately only the "standard connect" works:

connect(ui->celsiusDial, SIGNAL(valueChanged(int)), ui->celsiusLcd,SLOT(display(int)));

Spinning the dial leads to change on the LCD-Widget but anything else doesn't work (see the connect(...) calls in dialog.cpp.

The project have a QWidget with the name Dialog that calls the tempconverter.cpp class. Dialog.cpp:

#include "dialog.h"
#include "ui_dialog.h"
#include "tempconverter.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    TempConverter tempConverterObject(0, this);
    TempConverter * tempConverter = &tempConverterObject;


    connect(ui->celsiusDial, SIGNAL(valueChanged(int)), tempConverter, SLOT(setTempCelsius(int)));

    connect(ui->celsiusDial, SIGNAL(valueChanged(int)), ui->celsiusLcd, SLOT(display(int)));
    connect(tempConverter, SIGNAL(tempCelsiusChanged(int)), ui->celsiusDial, SLOT(setValue(int)));

    connect(ui->fahrenheitDial, SIGNAL(valueChanged(int)), tempConverter, SLOT(setTempFahrenheit(int)));

    connect(ui->fahrenheitDial, SIGNAL(valueChanged(int)), ui->fahrenheitLcd, SLOT(display(int)));
    connect(tempConverter, SIGNAL(tempFahrenheitChanged(int)), ui->fahrenheitDial, SLOT(setValue(int)));

}

Dialog::~Dialog()
{
    delete ui;
}

Here's my TempConverter-class:

Header: tempconverter.h

#ifndef TEMPCONVERTER_H
#define TEMPCONVERTER_H

#include <QObject>

class TempConverter : public QObject
{
    Q_OBJECT
public:
    TempConverter(int tempCelsius, QObject *parent = 0);

    int tempCelsius() const; // const is signature for getters!(that's why they are blue!)
    int tempFahrenheit() const;

public slots:
    void setTempCelsius(int);
    void setTempFahrenheit(int);

signals:
    void tempCelsiusChanged(int); // Signals are only declared not "implemented", they are emitted when a event occurs
    void tempFahrenheitChanged(int); // Signals are only declared not "implemented", they are emitted when a event occurs

private:
    int m_tempCelsius; // internal representation of celsiusTemp <=> Java Attribute
};

#endif // TEMPCONVERTER_H

Class: tempconverter.cpp

#include "tempconverter.h"
#include <QDebug>

TempConverter::TempConverter(int tempCelsius, QObject *parent) : QObject(parent) // this is the constructor
{
    qDebug("default constructor");
    m_tempCelsius = tempCelsius;
}


void TempConverter::setTempCelsius(int tempCelsius)
{
    //qDebug("setTempCelsius");
    if(m_tempCelsius == tempCelsius)
        return;
    m_tempCelsius = tempCelsius;

    emit tempCelsiusChanged(m_tempCelsius);
    emit tempFahrenheitChanged(tempFahrenheit());


}

void TempConverter::setTempFahrenheit(int tempFahrenheit){
    qDebug("setTempFahrenheit");
    int tempCelsius = (5.0/9.0)*(tempFahrenheit-32);
    setTempCelsius(tempCelsius);
    qDebug("setTempFahrenheit");
}

int TempConverter::tempCelsius() const{
    return m_tempCelsius;
}

int TempConverter::tempFahrenheit() const{
    return (m_tempCelsius*2)+30;
}

And finally my UI looks like this: dialog.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QWidget" name="">
   <property name="geometry">
    <rect>
     <x>30</x>
     <y>40</y>
     <width>331</width>
     <height>231</height>
    </rect>
   </property>
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QGroupBox" name="groupBox">
      <property name="title">
       <string>Celsius</string>
      </property>
      <widget class="QDial" name="celsiusDial">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>30</y>
         <width>161</width>
         <height>141</height>
        </rect>
       </property>
      </widget>
      <widget class="QLCDNumber" name="celsiusLcd">
       <property name="geometry">
        <rect>
         <x>3</x>
         <y>172</y>
         <width>161</width>
         <height>41</height>
        </rect>
       </property>
      </widget>
     </widget>
    </item>
    <item row="0" column="1">
     <widget class="QGroupBox" name="groupBox_2">
      <property name="title">
       <string>Fahrenheit</string>
      </property>
      <widget class="QDial" name="fahrenheitDial">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>20</y>
         <width>161</width>
         <height>141</height>
        </rect>
       </property>
      </widget>
      <widget class="QLCDNumber" name="fahrenheitLcd">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>170</y>
         <width>161</width>
         <height>41</height>
        </rect>
       </property>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

Thanks in advance, I really have no clue where the error is coming from.


Solution

  • The problem is that the tempConverterObject variable only exists in the constructor since it has been created in that context, ie it is a local variable and it is removed from memory when that function is executed. The solution is to convert that variable to a member of the class:

    *.h

    private:
        Ui::Dialog *ui;
        TempConverter *tempConverter;
    

    *.cpp

    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);    
        tempConverter = new TempConverter(0, this);
        connect(ui->celsiusDial, SIGNAL(valueChanged(int)), tempConverter, SLOT(setTempCelsius(int)));
    
        connect(ui->celsiusDial, SIGNAL(valueChanged(int)), ui->celsiusLcd, SLOT(display(int)));
        connect(tempConverter, SIGNAL(tempCelsiusChanged(int)), ui->celsiusDial, SLOT(setValue(int)));
    
        connect(ui->fahrenheitDial, SIGNAL(valueChanged(int)), tempConverter, SLOT(setTempFahrenheit(int)));
    
        connect(ui->fahrenheitDial, SIGNAL(valueChanged(int)), ui->fahrenheitLcd, SLOT(display(int)));
        connect(tempConverter, SIGNAL(tempFahrenheitChanged(int)), ui->fahrenheitDial, SLOT(setValue(int)));
    
    }