PDA

View Full Version : MainWindow GUI cannot call SLOT in worker thread UDP object



kma005
8th March 2018, 04:11
Hello,

I am unable to emit() a signal from the MainWindow object to a worker thread that will send & receive UDP Data.
The goal is to learn how to communicate from the GUI thread to the UDP thread.
***I do not understand why the SLOT is not working. I used the Mandlebrot example but in reverse, by communicating from GUI to thread. I tried QT4 & QT5 connect(signal, slot) functions without success. I get zero errors/warnings @ compile time***

Mandlebrot example:

connect(&thread, SIGNAL(renderedImage(QImage,double)), this, SLOT(updatePixmap(QImage,double)));

Mine in mainwindow.cpp:

connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);

They only message I get from the "Application Output" is:

QObject::connect: Parentheses expected, signal MainWindow::&MainWindow::runInitializeInthreadUDP in mainwindow.cpp:36


Please see the attached code and if anyone is able to help, that would be very much appreciated.
If more info is needed, please ask.

//main.cpp


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


int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<<"From main GUI thread: "<<QThread::currentThreadId();


//Create GUI, but it is not shown until GUI.show is called
MainWindow GUI;
//generate GUI screen when this main function is finished
GUI.show();

return a.exec();
}


//mainwindow.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtCore>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0); //Class constructor

private:
Ui::MainWindow *ui;

signals:
void runInitializeInthreadUDP();

private slots:
void on_pushButton_clicked();
};

#endif // MAINWINDOW_H


//mainwindow.cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include "myudp.h"
#include "myThread.h"


myThread* threadObj = new myThread();
Worker* worker = new Worker();


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

//Create UDP object and startup worker thread
//https://wiki.qt.io/QThreads_general_usage
MyUDP udpObj;
udpObj.moveToThread(threadObj);
connect(worker, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (quit()));
connect(worker, SIGNAL (&Worker::threadFinishedSignal), worker, SLOT (deleteLater()));
connect(threadObj, SIGNAL (&Worker::threadFinishedSignal), threadObj, SLOT (deleteLater()));
threadObj->start();


//
//
//THIS NEXT PART DOES NOT WORK(Initialize() SLOT() function is never called)!!!!
//
//
//initialize UDP ports
//QT5 VERSION:
connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);
//QT4 VERSION:
// connect( this, SIGNAL(runInitializeInthreadUDP()), threadObj, SLOT(Initialize()), Qt::QueuedConnection);
emit runInitializeInthreadUDP();
}


//also does not work when pressing button on GUI (this _clicked function runs, but does not call SLOT &MyUDP::Initialize)
void MainWindow::on_pushButton_clicked()
{
emit runInitializeInthreadUDP();
}


//mythread.h


//#ifndef WORKERTHREAD_H
//#define WORKERTHREAD_H

#include <QtCore>


//http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
class myThread : public QThread
{
Q_OBJECT

private:
void run()
{
qDebug()<<"From worker thread: "<<currentThreadId();
connect(this, &QThread::finished, this, &QObject::deleteLater);

exec();
}
};



//https://wiki.qt.io/QThreads_general_usage
class Worker : public QObject {
Q_OBJECT

signals:
void threadFinishedSignal();
};

//#endif // WORKERTHREAD_H


//myudp.h


#ifndef UDP_H
#define UDP_H

//Base class QObject
#include <QUdpSocket>
#include <QtCore>


class MyUDP : public QObject
{
Q_OBJECT

public:
MyUDP(); //Constructor for UDP Class Object
~MyUDP(); //Destructor for UDP Class Object

private:
QUdpSocket *socket;

public slots:
void UDPreadInputData();
//Setup UDP port and connect port to fire function each time a UDP packet is received
void Initialize();
};


#endif // UDP_H


//myudp.cpp


#include "myudp.h"
#include <QtCore>


//Settings for UDP addresses
QHostAddress remoteAddress = QHostAddress("192.168.1.1");
QHostAddress localAddress = QHostAddress("192.168.1.2");
quint16 sendPort = 1234;
quint16 receivePort = 5678;

//UDP buffer that will contain the data received from microcontroller
QByteArray Buffer;



MyUDP::MyUDP() //Constructor for UDP Class Object
{
}
MyUDP::~MyUDP() //Destructor for UDP Class Object
{
}



void MyUDP::Initialize()
{
socket = new QUdpSocket(this);

//We need to bind the UDP socket to an address and a port
// socket->bind(QHostAddress::LocalHost,receivePort);
socket->bind(localAddress,receivePort);
//Call the "UDPreadyRead" function each time the socket gets data on the defined UDP port
connect(socket,SIGNAL(readyRead()),this,SLOT(UDPre adInputData()));

qDebug()<<"UDP worker thread initialized";
}



//Read something
void MyUDP::UDPreadInputData()
{
Buffer.resize(socket->pendingDatagramSize());
int bufferSize = Buffer.size();

//read sing UDP packet from hardware ethernet tranceiver on computer
socket->readDatagram(Buffer.data(), bufferSize, &remoteAddress, &receivePort);

// http://lists.qt-project.org/pipermail/qt-interest-old/2009-June/008318.html
// Read float32 data types out with a QDataStream
QDataStream ds( Buffer.mid( 0, bufferSize ) );
//By default, a QDataStream is big endian and must be flipped depending on "processor architecture".
ds.setByteOrder(QDataStream::LittleEndian);
ds.setFloatingPointPrecision(QDataStream::SinglePr ecision);

//Throw out UDP Ethernet header and two bytes that are unused at beginning of packet (10 bytes)
for(int i; i<5; i++)
{
qint16 temp; //each int16 is 2 bytes
ds >> temp;
}

//Read the first two "start of sample bytes"
qint16 HeaderByte1;
ds >> HeaderByte1; //54321 start of sample int16
}

d_stranz
8th March 2018, 16:42
connect( this, SIGNAL(&MainWindow::runInitializeInthreadUDP), threadObj, SLOT(&MyUDP::Initialize), Qt::QueuedConnection);

You are mixing up the two different styles for the connect() statement. Your code -should- read:



connect( this, &MainWindow::runInitializeInthreadUDP, threadObj, &MyUDP::Initialize, Qt::QueuedConnection);

high_flyer
9th March 2018, 21:56
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtCore>
#include "myudp.h"
#include "myThread.h"


myThread* threadObj = new myThread();
Worker* worker = new Worker();


//MainWindow Class Constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),

That really hurts my eyes and brains.
This is C++ not C and even in C you use globals only if really really needed.