1

I have some troubles in correct set of Signal and Slots between one class in which I do some calculations and the other one which contain GUI with my progress bar. I have very small experience with qt so I don't feel well how the signal/slots works. I tried few manuals and tutorials but I still don't know how to set it.

Let's call the progress bar class mainwindow

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow: public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow*ui;
};

#endif // LOADING_H

mainwindow.cpp

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->progressBar->setValue(0);
    calc sender;
    connect(&sender, SIGNAL( inprogress(int) ), ui->progressBar, SLOT( setValue(int) ) );
}


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

void MainWindow::on_pushButton_clicked()
{
    calc clc;
    clc.doData();
}

Signal is emitted from calculation class, call it short calc

calc.h

#ifndef CALC_H
#define CALC_H

#include <QObject>

class calc : public QObject
{
Q_OBJECT
public:
    calc(QObject *parent=0);
    void doData();
    void printResults(int t);
signals:
    void inprogress(int progr);

};

#endif // CALC_H

calc.cpp

#include "calc.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

int t = 0;
int t_end = 100;
int progr = 0;

void calc::printResults(int t)
{
    progr = t;
    emit inprogress(progr);
    QCoreApplication::processEvents(); //Prevent GUI freeze.
}

void calc::doData()
{
    for ( int i = 1; i <= t_end; i++ )
    {
        t++;
        printResults(t);
        qDebug()<<t;
    }
}

calc::calc(QObject *parent)
{

}

Archiev part (code above edited) The compilation ends with this error: no matching function for call to 'loading::connect(calc*, const char*, QProgressBar*&, const char*) Do I use signals in correct way, or I misunderstand this concept? What's the >correct way to update value of progress bar during this calculations?

EDIT: Code edited to be more clear, now it show current question - signal works but has no effect on qprogressbar.

EDIT2: Now works - function has to be call sender->doData(). Additionally correct assignment is sender = new calc(this) (with calc *sender added to private section of mainwidnow.h). Thanks you, everyone, for help, especially @eyllanesc for point correct way!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Karls
  • 731
  • 7
  • 17
  • calc must be QObject-based. sod right way is class calc : public QObject { Q_Object public: calc(QObject *prnt) : QObject(prtn) {....} ..... And you create your calc but you didn't strore it. So when you go out of constructor scope your calc exemplar will be destroyed – Andrey Semenov Sep 04 '17 at 12:23
  • At what time do you call the doData function? – eyllanesc Sep 05 '17 at 13:47
  • it's called when user push buton placed under progress bar, look: `void MainWindow::on_pushButton_clicked()` – Karls Sep 05 '17 at 13:50

2 Answers2

0

Only the classes that inherit from QObject can have signals, in addition they must have the Macro Q_OBJECT, since this through the MOC creates all the necessary metaclass for the connection between signals and slots. In your case:

*.h

class calc: public QObject
{
Q_OBJECT
    public:
        calc(QObject *parent=0);
        void signalProgress();
    signals:
        void inprogress();

};

*.cpp

[...]

calc::calc(QObject *parent): QObject(parent)
{

}

Also create a calc instance through a pointer as the garbage collector will delete that data after you use the constructor.

*.h

private:
    Ui::loading *ui;
    calc *sender;

*.cpp

loading::loading(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::loading)
{
    ui->setupUi(this);
    ui->progressBar->setValue(0);
    sender = new calc(this);
    connect(sender, SIGNAL( inprogress(int) ), ui->progressBar, SLOT( setValue(int) ) );
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Comments are not for extended discussion or debugging sessions; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/153687/discussion-on-answer-by-eyllanesc-qprogressbar-connect-progress-between-classes). If you have a follow-up question or want to share more code, edit the question. If there is something that needs to be clarified about this answer, edit it. – Cody Gray - on strike Sep 05 '17 at 12:48
  • Thanks for your advice, question edited with full code. – Karls Sep 05 '17 at 13:09
0

You need to use QObject-based class in order to establish a connection

In your calc header file, you will have to inherit from QObject and then to add the Q_OBJECT macro

calc.h

class calc : pubilc QObject
{
   Q_OBJECT
public:
    calc();
    void signalProgress();
signals:
    void inprogress(int progr);

};

There's tons of examples and documentation using Qt signals & slots you can start reading here

P.S.

QProgressBar is also Object-based class so the same logic is already implemented here.

Simon
  • 1,522
  • 2
  • 12
  • 24
  • Thank you for the answer, but as I said in previous answer (which was delated, I don't know why) after this changes it compiles, but `emit` has no effect on progress bar. It always stay at default value. I did some test in different configurations and it seems that it works only if executed in specific way. Look at this exampel from previouse discusion: https://gist.github.com/eyllanesc/b2e2d63ea8bfe1b4e6e580f9ba0eddbc But if you move `emit` from `connect(timer, &QTimer::timeout, [this]{ signalProgress();progr++;qDebug()< – Karls Sep 05 '17 at 12:26
  • I edited my code to be more specific, now it's more clear in which way I need to call `emit`. – Karls Sep 05 '17 at 12:40