PDA

View Full Version : Signals- Slots; emit one signal from one Form to multiple forms + mainwindow



malone
24th January 2019, 13:11
Hello community,
i have one class called mInterface(mInterface.cpp + mInterface.h) that reads data from udpSocket and then send those data to mupltiple(2) Forms(.ui) and mainwindow. i use Signals and slots communication to emit the data to all another forms.
normally, when i start my project i have to read datagram from udpsocket and then directly emit received data to Forms of my projects. Reading of datagram runs fine but the transfer of data to other forms doesn't works well. Only one Form receives transmitted data and the ather not. all classes Form are written in the same way but i don't understand why only one Form receives transmitted signal(data).
according to the signals/slots communication we can emit one signal to more slots from multiple objects or Form(.ui). if yes, why my project not works? somebody have an idea?
in advance, thank you for your help.

//mInterface.cpp class



#include "minterface.h"

mInterface::mInterface(QObject *parent) : QObject(parent)
{
readSocket = new QUdpSocket(this);
readSocket->bind(QHostAddress::LocalHost, 50885);
connect(readSocket, SIGNAL(readyRead()), this, SLOT(receiveData()));
}

void mInterface::receiveData()
{
QByteArray rDatagram;

do
{
rDatagram.resize(int(readSocket->pendingDatagramSize()));
readSocket->readDatagram(rDatagram.data(), rDatagram.size());
} while(readSocket->hasPendingDatagrams());

QDataStream stream(&rDatagram, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_9);
memccpy(&arrChannels, (const void *)rDatagram.data(), sizeof(arrChannels), sizeof(arrChannels));

//int nombre = qrand()%(101);
qDebug()<<"mInterface : "<<arrChannels[0].AC_Volt;
emit dataAllChannels(arrChannels[0].AC_Volt);

}


form1.cpp


#include "readform.h"
#include "ui_readform.h"

ReadForm::ReadForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ReadForm)
{
ui->setupUi(this);
connect(&interface, SIGNAL(dataAllChannels(float)), this, SLOT(setReadData(float)));
qDebug()<<"readform constructor";
}

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


void ReadForm::setReadData(float d)
{

qDebug()<<"readform : "<<d;
ui->lcdNumber->display(d);
}

void ReadForm::on_pushButton_clicked()
{
mform2.show();
}


form2.cpp


#include "form2.h"
#include "ui_form2.h"

Form2::Form2(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form2)
{
ui->setupUi(this);
connect(&form2, SIGNAL(dataAllChannels(float)), this, SLOT(meinSlot(float)));
qDebug()<<"readform2 constructor";
}

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

void Form2::meinSlot(float f2)
{
ui->lcdNumber->display(f2);
qDebug()<<"readform2 : "<< f2;
}



//mainwindow.cpp



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

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(&m, SIGNAL(dataAllChannels(float)), this, SLOT(readAllValue(float)));
qDebug()<<"Mainwindow constructor";
}

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

void MainWindow::readAllValue(float c)
{
qDebug()<<"Read Mainwindow : "<<c;
ui->lcdNumber->display(c);
}

void MainWindow::on_pushButton_clicked()
{
readform.show();
}



//main.cpp



#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

Lesiok
24th January 2019, 15:16
At 99, (9)% error is on your side.
1. You did not say which form receives the signal and which is not.
2. You did not show h files.

d_stranz
24th January 2019, 16:53
I agree with Lesiok. You need to show the -complete code- not just the part you think is important.

My guess is that in every one of the signal / slot connections you are making, you are using a different instance of your "mInterface" class. I say this because in each of the connect() statements, it looks like you are using the address of a member variable (&interface) instead of a pointer. That tells me you are probably creating that variable on the stack during the construction of your forms and are not passing in the address of the single mInterface instance that is the one receiving the data. Only the first instance created does anything, because after it has been bound to the read socket, the other calls to bind() fail (but you don't bother to check to see if the bind() was successful...).

malone
24th January 2019, 19:18
Thank you for your feedback,



Lesiok
At 99, (9)% error is on your side.
1. You did not say which form receives the signal and which is not.

mainwindow, readform and form2 have to receive the signal. i can see that.


mInterface.h



#ifndef MINTERFACE_H
#define MINTERFACE_H

#include <QUdpSocket>
#include <QDataStream>


class mInterface : public QObject
{
Q_OBJECT
public:
explicit mInterface(QObject *parent = nullptr);



signals:
void dataAllChannels(double);

public slots:
void receiveData();

private:
QUdpSocket *readSocket;
};

#endif // MINTERFACE_H


readform.h



#ifndef READFORM_H
#define READFORM_H

#include <QWidget>
#include <minterface.h>
#include <QDebug>

namespace Ui {
class ReadForm;
}

class ReadForm : public QWidget
{
Q_OBJECT

public:
explicit ReadForm(QWidget *parent = nullptr);
~ReadForm();

private slots:
void setReadData(float);

private:
Ui::ReadForm *ui;
mInterface interface;
Form mform2;
};

#endif // READFORM_H


form2.h




#ifndef FORM2_H
#define FORM2_H

#include <QWidget>
#include <minterface.h>
#include <QDebug>

namespace Ui {
class Form2;
}

class Form2 : public QWidget
{
Q_OBJECT

public:
explicit Form2(QWidget *parent = nullptr);
~Form2();

private slots:
void meinSlot(float);

private:
Ui::Form2 *ui;
mInterface form2;
};

#endif // FORM2_H









mainwindow.h




#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>

#include <minterface.h>
#include <readform.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void readAllValue(floatc);

private slots:
void on_pushButton_clicked();
void on_pushStop_clicked();

private:
Ui::MainWindow *ui;
mInterface m;
ReadForm readform;

};

#endif // MAINWINDOW_H

d_stranz
24th January 2019, 20:17
As I guessed:

class ReadForm has a member variable of type mInterface.
class Form2 has a member variable of type mInterface.
class MainWindow has a member variable of type mInterface.

When constructed, these become three completely independent instances of the mInterface class. Only one of them (whichever is constructed first - probably the one in the MainWindow instance constructed in main.cpp) will be successfully be bound to the socket and receive packets. For the other two, the call to bind() will fail because another instance got there first to bind the socket.

You need to rethink your design and consider how a single instance of a class can be shared among multiple other class instances. It isn't hard - I gave you a hint in my previous answer.

malone
24th January 2019, 21:39
Thank you for your contribution,


I agree with Lesiok. You need to show the -complete code- not just the part you think is important.

My guess is that in every one of the signal / slot connections you are making, you are using a different instance of your "mInterface" class. I say this because in each of the connect() statements, it looks like you are using the address of a member variable (&interface) instead of a pointer. That tells me you are probably creating that variable on the stack during the construction of your forms and are not passing in the address of the single mInterface instance that is the one receiving the data. Only the first instance created does anything, because after it has been bound to the read socket, the other calls to bind() fail (but you don't bother to check to see if the bind() was successful...).

I think you are right. When I started the program found that the constructor of the class "mInterface" was called 3 times so 3 different instance of mInterface. once by calling the class Mainwindow + once by calling the class Readform and once by calling the class Form2. When i try with pointer by it is the same. I declared a pointer of mInterface in mainwindow, form2 and readForm for signals/slots-connection but nothing else happening only the same result.
How can i do that(to declare only one instance of mInterface )? can you give me a example?
thanks.

Added after 1 8 minutes:


As I guessed:

class ReadForm has a member variable of type mInterface.
class Form2 has a member variable of type mInterface.
class MainWindow has a member variable of type mInterface.

When constructed, these become three completely independent instances of the mInterface class. Only one of them (whichever is constructed first - probably the one in the MainWindow instance constructed in main.cpp) will be successfully be bound to the socket and receive packets. For the other two, the call to bind() will fail because another instance got there first to bind the socket.

You need to rethink your design and consider how a single instance of a class can be shared among multiple other class instances. It isn't hard - I gave you a hint in my previous answer.

it runs very well. Thank you very much for your help.