PDA

View Full Version : struct type object with signal/slot method



eliosm
19th April 2017, 20:38
Hi, i'm new to Qt (started on: C- 5 years ago; C++ June last year; Qt - since this January) and i got some questions... i'm trying stuff for the past week but unsuccessful:
1. How can i make a struct visible in another class so i can create instances of it in diferent headers? (Like in mainwindow.h above) (This is a c++ question, i know..)
2. After i got it working, i saw in this forum that i got to add my struct to qt metatype so i can use signal/slot. I got to do it inside the header or the cpp file where i declared it?

I just made a clean project:
main.cpp (default code)
|-mainwindow.ui (just a start button on it)
|-mainwindow.h
|-mainwindow.cpp
|-myclass.h
|-myclass.cpp



mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QString>
#include <QDebug>
#include "myclass.h"

namespace Ui {
class MainWindow;
}
struct myStruct{
int id;
QString name;
float height;
};

class MainWindow : public QMainWindow
{
Q_OBJECT

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

void startProgram();

signals:
void sendToClass(myStruct data[5]);

private slots:
void on_pushButton_clicked();

private:
void send();
Ui::MainWindow *ui;
myclass mcObj;
myStruct data[5];
};

#endif // MAINWINDOW_H


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::startProgram()
{
data[0].id = 1001;
data[0].name = "Mark";
data[0].height = 1.78f;

emit sendToClass(data);
}

void MainWindow::on_pushButton_clicked()
{
connect(this, &MainWindow::sendToClass, &mcObj, &myclass::receiveFromMain);
startProgram();
}



myclass.h:

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QObject>

class myclass : public QObject
{
Q_OBJECT
public:
explicit myclass(QObject *parent = 0);

void startStuff();

public slots:
void receiveFromMain();
};

#endif // MYCLASS_H



myclass.cpp:

#include "myclass.h"

myclass::myclass(QObject *parent) : QObject(parent)
{

}

void myclass::startStuff()
{

}

void myclass::receiveFromMain()
{
//Want to receive the struct here!
}




I left it in blank because i just don't know how to make it!

Basically, in my real project i want to be able to receive position parameters from a socket class running with QtConcurrent, and pass it to several classes.. i could just pass: int id, QString Name, float x, float y, float z.... but it is much more clean with a struct or class!

that struct can be anywhere (or even transform it to a class, better for me..).. i just want it to be seen in almost every project files.. although i don't want to create global variables.. I just tried several ways and i can't do it.




Thank you in advance! :)

d_stranz
20th April 2017, 23:37
Passing a struct is no different from passing any other type of variable. Defining a metatype is only needed if you want to serialize it using Qt's stream serialization methods. And signals and slots are nothing except ordinary C++ methods with some fancy Qt macros to keep moc and the preprocessor busy when they compile your code. So you writ something like this:



// myClass.h

// ...
public slots:
void receiveFromMain( const std::vector< myStruct > & info );
//...


// myClass.cpp

void myClass::receiveFromMain( const std::vector< mSystruct > & info )
{
// do stuff with mystruct contents
}

// MainWindow.h
#include <vector>

// ...

signals:
void sendToClass( const std::vector< myStruct > & info );

private:
std::vector< myStruct > data;
myclass * mcObj;
};


// MainWindow.cpp

MainWindow::MainWindow( QWidget * parent ) : QMainWindow( parent )
{
// setup ui, etc.
mcObj = new myclass( this ); // Create on the heap, not the stack
data.resize( 5 );

connect(this, &MainWindow::sendToClass, mcObj, &myclass::receiveFromMain); // do this only once.
}

void MainWindow::on_pushButton_clicked()
{
startProgram();
}


I changed from a fixed sized structure for data to a variable-sized one that uses std::vector. You could use QVector instead. Your mcObj instance should be allocated on the heap using new() instead of on the stack as you had it. Giving it the instance of MainWindow ("this") as a parent ensures it will be destroyed when the MainWindow instance is. Otherwise, you were almost there.

eliosm
20th April 2017, 23:57
Hi d_stranz, i tried to delete this post next morning but without any luck. I was just too tired! 4 days programming all the time and sleeping 5/6 hours a day.. not good! I knew I had to rest! After some beers, girlfriend, and 9h of sleep i tried again and i just solved it in minutes! I did it with struct, with class, and even completed the threading stuff i wanted to do...

Anyway, you created a standard vector... why not QVector?

Thank you for reply!

d_stranz
21st April 2017, 00:07
Anyway, you created a standard vector... why not QVector?


No reason except that I use the C++ standard template library (STL) in preference to the Qt library when equivalent classes exist in both. Much of the non-GUI code I write has to be portable as libraries used in non-Qt applications, so I have just adopted the habit of using the STL everywhere possible. If I were to write something using Qt container classes that I later decided should be shared in a library, then I have a bunch of rewriting and testing to convert it to STL when I could have done it that way in the first place.

That said, QVector has the same semantics as std::vector and can be used in any of the STL or boost algorithms that operate on containers that implement random iterator access.