NickDeal
NickDeal

Reputation: 45

Transfer data between forms in Qt

I have a school project where I am using Qt to drive my GUI interface. I need to know the best way or the easiest way to transfer a vector of class objects between the different .cpp files for the different forms. I was thinking of including the .h files and making a setPointer and getPointer that points to the vector, but is there a better way?

Thanks for the help

Upvotes: 1

Views: 8887

Answers (9)

dallyshalla
dallyshalla

Reputation: 11

Here is a simple explanation:

Take two forms:

Dialog windows Dashboard and Sensor

on Dashboard:

#ifndef DASHBOARD_H
#define DASHBOARD_H

#include "sensor.h"
#include <QDialog>

namespace Ui {
class dashboard;
}

class dashboard : public QDialog
{
    Q_OBJECT

public:
    explicit dashboard(QWidget *parent = 0);

    QTimer *timer;

    ~dashboard();

public slots:
    void MyTimerSlot();


private slots:
    void on_pushButton_clicked();

private:
    Ui::dashboard *ui;
    double mTotal;
    sensor *snsr;
};

#include "dashboard.h"
#include "ui_dashboard.h"
#include <QDebug>
#include <QTimer>
#include <QMessageBox>

dashboard::dashboard(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::dashboard)
{
    ui->setupUi(this);

    this->setWindowTitle(QString("dashboard"));
    // create a timer
    timer = new QTimer(this);

    // setup signal and slot
    connect(timer, SIGNAL(timeout()),
          this, SLOT(MyTimerSlot()));

    timer->stop();

    mTotal = 0;
    snsr = new sensor(this);
    // msecx
}

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

void dashboard::on_pushButton_clicked()
{
    snsr->show();
}

void dashboard::MyTimerSlot()
{
    mTotal += 1;
    snsr->setValue(mTotal);
    ui->sensorlabel->setText(QString::number(mTotal));
}

Now on Sensor: sensor.h

#ifndef SENSOR_H
#define SENSOR_H
#include <QTimer>

#include <QDialog>

namespace Ui {
class sensor;
}

class sensor : public QDialog
{
    Q_OBJECT

public:
    explicit sensor(QWidget *parent = 0);

    ~sensor();

public slots:
    void setValue(double value);

signals:
    void changeLabel();
    void valueChanged(double newValue);

private:
    Ui::sensor *ui;
    double mTotal;
};

#endif // SENSOR_H

sensor.cpp

#include "sensor.h"
#include "ui_sensor.h"
#include "dashboard.h"

sensor::sensor(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::sensor)
{
    ui->setupUi(this);

    this->setWindowTitle(QString("sensor"));

    connect(this, SIGNAL(valueChanged(double)), this, SLOT(changeLabel()));
}


void sensor::changeLabel()
{
    ui->sensorlabel->setText(QString::number(mTotal));
}

void sensor::setValue(double value)
{
    if (value != mTotal) {
        mTotal = value;
        emit changeLabel();
    }
}

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

Upvotes: 0

Md. Minhazul Haque
Md. Minhazul Haque

Reputation: 638

  1. Let's assume that, you are using two forms. formA and formB.
  2. Create a signal and slot in forma.cpp

    public slots: void receiveData(QVectorobjects);

    signals: void sendData(QVector);

    Do the same for formb.cpp.

  3. Now connect formA and formB like this.

    connect(formA, SIGNAL(sendData(QVector<MyClass>)), formB, SLOT((receiveData(QVector<MyClass>)));

    connect(formA, SIGNAL(receiveData(QVector<MyClass>)), formB, SLOT((MyClass(QVector<MyClass>)));

  4. Now formA will share data (set of objects) when you write emit sendData(QVector() << objA << objB); and formB will catch it!

Enjoy the magic of signal and slot. :)

Upvotes: 4

NickDeal
NickDeal

Reputation: 45

I ended up using the extern keyword. I looked in to custom signals and slots and I think that it would be the better way to go, but given time and the fact that this is for school I went with the fast and dirty way for now.

Upvotes: 0

Phlucious
Phlucious

Reputation: 3843

Use QVector or QList or any number of Qt's container classes. You can pass an iterator to your forms, or a reference (QList::operator[]) to the form so that you're not copying the data.

If you want to pass the whole vector, pass it as a reference. For example:

//pass the whole vector as for read-write
void doStuffOnMany(QList<MyClass>& listref) {}  //declaration
...
QList<MyClass> mylist;                          //usage
doStuffOnMany(mylist);

//read-only
void doStuffOnMany(const QList<MyClass>& listref) {}

//pass one portion of the vector for read-write
void doStuffOnOne(MyClass& classref) {}         //declaration
...
QList<MyClass> mylist;                          //usage
doStuffOnOne(mylist[0]);

Also, the Qt container classes are implicitly shared, so you don't even necessarily have to pass a reference to the vector if you need good performance.

Upvotes: 0

Md. Minhazul Haque
Md. Minhazul Haque

Reputation: 638

What about extern keyword? But Qt's signal slot is safe.

Upvotes: 0

Murtuza Kabul
Murtuza Kabul

Reputation: 6524

Depending upon your usage, there can be at least two ways.

First is to create a public variable in your class (form) to which you can assign the current value of the vector (pointer) so that you can access it in that class.

Another option is to create a singleton class in the application and store the vector pointer inside that class. This will allow access to this class throughout the application.

Based on your requirement, if you want the vector to stay alive for the application life, you should opt the second option, otherwise opt the first option.

Upvotes: 0

borisbn
borisbn

Reputation: 5054

The best way to transfer data between Qt-classes is to use signal/slot system.

Pay an attention, that if you want to transfer data with type differ from standard C++ and Qt, you should register it's type with qRegisterMetaType

Upvotes: 0

dtech
dtech

Reputation: 49309

First of all, Qt container classes are implicitly shared, that means you can pass them by value, and only a shallow copy will occur. If you attempt to modify the container, then a new copy will be created. So there is no need to use pointers in that particular case.

Then, use signals and slot to do the actual data transfer - the common pattern is for the parent widget to manage its child widgets, and it is that parent class that the actual passing of data usually takes place.

Upvotes: 0

Dimitry Ernot
Dimitry Ernot

Reputation: 6594

You should use custom signals and slots. Your main window can connect signal and slot between each form.

In this way, you forms are independent of each other (i.e. doesn't need a pointer).

Upvotes: 1

Related Questions