1

Hi I'm teaching myself Qt based on Qt 5.7.0 (MSVC 2013, 32 bit), Qt Creator 4.1.0 - community edition. I am using an book, "Programming with Qt, 2nd Edition" by Matthias Kalle Dalheimer which focuses on QT3. One of the exercises is to have a slider which uses the LCD number display. There are also two buttons (add, subtract) to change the slider and LCD display. I was not able to get the book code to work because there have been major syntax changes.

I was able to get my code to work using the Qt designer but I want to do it without that as well. How can I do that? I was thinking of using events but I couldn't figure out the syntax.

Here is the snippets from the book.

QObject::connect(decrement, SIGNAL(clicked()), myslider, SLOT(subtractStep()));
QObject::connect(increment, SIGNAL(clicked()), myslider, SLOT(addStep()));

These are the error messages from the console for my code below in main.cpp: "QObject::connect: No such slot QSlider::SingleStep()in ..\ProgrammingQt\main.cpp:31 QObject::connect: No such signal QSlider::triggerAction(SliderSingleStepAdd) in ..\ProgrammingQt\main.cpp:32"

Here is my code without the ui. - main.cpp

#include <iostream>

#include <qapplication.h>
#include <qwidget.h>
#include <qslider.h>
#include <qlcdnumber.h>
#include <qpushbutton.h>
#include <qstring.h>

using namespace std;

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget *widget = new QWidget();
    widget->setGeometry(400, 300, 170, 150);

    QSlider *slider = new QSlider(Qt::Horizontal, widget);
    slider->setGeometry(10, 10, 150,30);

    QLCDNumber *lcd = new QLCDNumber(2, widget);
    lcd->setGeometry(60, 50, 50, 50);
    lcd->display(1);

    QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));

    QPushButton *addBtn = new QPushButton("ADD ONE", widget);
    addBtn->setGeometry(10, 110, 50, 30);
    //QObject::connect(addBtn, SIGNAL(clicked(bool)), slider, SLOT(SliderSingleStepAdd()));
    //QObject::connect(addBtn, SIGNAL(clicked(bool)), slider, SLOT(SingleStep()));
    //QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));

    QPushButton *minusBtn = new QPushButton("MINUS ONE", widget);
    minusBtn->setGeometry(100, 110, 60, 30);
   //  QObject::connect(minusBtn, SIGNAL(clicked(bool)), slider, SLOT    (SliderSingleStepSub()));

    QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));

    widget->setWindowTitle("LCD Number");
    widget->show();
    return app.exec();
}

Here is the code using the Qt Designer: mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

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

void MainWindow::on_slider_valueChanged(int value)
{
    ui->lcd->display(value);
}

void MainWindow::on_addBtn_clicked()
{
    int incVal = ui->slider->value();
    incVal++;
    ui->slider->setValue(incVal);
    ui->lcd->display(incVal);
}

void MainWindow::on_minusBtn_clicked()
{
    int decVal = ui->slider->value();
    decVal--;
    ui->slider->setValue(decVal);
    ui->lcd->display(decVal);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSlider>
#include <QLCDNumber>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();

   private slots:

   void on_slider_valueChanged(int value);

   void on_addBtn_clicked();
   void on_minusBtn_clicked();

 private:
     Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
jmjiru
  • 11
  • 3
  • 2
    Qt3 was so different from Qt4 and Qt5, that it's probably not very useful trying to use Qt3 book here... Qt4 book would work because Qt5 is almost source-compatible with Qt4. But Qt5 introduces new, superior ways of doing many things, so your time would be better spent learning from Qt5 material. – hyde Oct 20 '16 at 05:28
  • unfortunately there weren't any newer QT books in my local libraries. – jmjiru Oct 20 '16 at 05:37
  • 2
    Qt has great online documentation available for Qt 5 and Qt 4 – demonplus Oct 20 '16 at 05:57
  • Try googling "C++ GUI Programming with Qt 4 pdf" (not sure if what Google finds with that is legit, download on your own discretion). And check out https://wiki.qt.io/Books and consider suggesting your library to get some fresher material for Qt5 (or buy some yourself, if that's an option, of course). – hyde Oct 21 '16 at 11:53

1 Answers1

0

The slots SliderSingleStepAdd, SingleStep or SliderSingleStepSub are not found because there are not defined in the object slider.

According to the documentation,

All classes that inherit from QObject or one of its subclasses (e.g., QWidget) can contain signals and slots.

So you need a class where you must implement your required signals and slots.

For example, your main should be something like this:

#include <iostream>

#include <qapplication.h>
#include <qwidget.h>
#include <qslider.h>
#include <qlcdnumber.h>
#include <qpushbutton.h>
#include <qstring.h>
#include <myclass.h>

using namespace std;

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    MyClass myClass;

    QWidget *widget = new QWidget();
    widget->setGeometry(400, 300, 170, 150);

    QSlider *slider = new QSlider(Qt::Horizontal, widget);
    slider->setGeometry(10, 10, 150,30);

    QLCDNumber *lcd = new QLCDNumber(2, widget);
    lcd->setGeometry(60, 50, 50, 50);
    lcd->display(1);

    QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));

    QPushButton *addBtn = new QPushButton("ADD ONE", widget);
    addBtn->setGeometry(10, 110, 50, 30);
    QObject::connect(addBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SliderSingleStepAdd()));
    QObject::connect(addBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SingleStep()));
    // QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));

    QPushButton *minusBtn = new QPushButton("MINUS ONE", widget);
    minusBtn->setGeometry(100, 110, 60, 30);
    QObject::connect(minusBtn, SIGNAL(clicked(bool)), &myClass, SLOT(SliderSingleStepSub()));

    QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));

    widget->setWindowTitle("LCD Number");
    widget->show();
    return app.exec();
}

And you should have a class like the following one:

#ifndef MYCLASS_H
#define MYCLASS_H

#include <iostream>
#include <QObject>

class MyClass : public QObject
{
   Q_OBJECT

public:
    MyClass(): QObject() {}
    virtual ~MyClass() {}

   public slots:
    void SliderSingleStepAdd ()
    {
        std::cout << "SliderSingleStepAdd" << std::endl;
    }

    void SingleStep ()
    {
        std::cout << "SingleStep" << std::endl;
    }

    void SliderSingleStepSub ()
    {
        std::cout << "SliderSingleStepSub" << std::endl;
    }

};

#endif // MYCLASS_H

In my opinion, all your objects (slider, lcd and buttons) should be in a class that inherits from QWidget so you can connect those objects. This should be also necessary in case of the following connect:

QObject::connect(slider, SIGNAL(triggerAction(SliderSingleStepAdd)), lcd, SLOT(display(int)));
Tarod
  • 6,732
  • 5
  • 44
  • 50