PDA

View Full Version : Adding own slot to a signal from mainWindow



Brixus
25th March 2014, 18:34
Hello,

I would like to connect a slider I have created in "Design mode" with an own slot I have written into a new class.

The slider is named g_sld.

I get the error. "expected primary-expression before '->' token" in the main.cpp
Google couldnt help me and as I am a C++ beginner I dont unterstand the mistake.
Can anybody tell me whats wrong?

Thank you very much :-)

See the code following:

Headers:

#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:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H




#ifndef MYSLOTS_H
#define MYSLOTS_H

#include <QObject>

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

signals:


public slots:
void writeValue (int);

private:
int val;

};

#endif // MYSLOTS_H


Sources:
main.cpp

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

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

QObject::connect(MainWindow->g_sld, SIGNAL(valueChanged (int)),SLOT(writeValue(int)));

return a.exec();
}


mywindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
using namespace std;

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

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


myslots.cpp

#include "myslots.h"
#include <iostream>
using namespace std;

mySlots::mySlots(QObject *parent) :
QObject(parent)
{
int val=0;
}

void mySlots::writeValue (int x)
{
if (x != val)
{
cout << x << endl;
val = x;
}
}

Radek
25th March 2014, 19:14
connect(MyWindow.ui->g_sld,...);

supposing g_sld is a pointer.

Brixus
25th March 2014, 19:35
Thanks,

actually g_sld is just in the Form "mainwindow.ui" and I am not sure whether g_sld is automatically a pointer or how to set a pointer to this.

ChrisW67
25th March 2014, 20:18
The error arises because the first argument to connect is wrong but there are several issues here.


QObject::connect(MainWindow->g_sld, SIGNAL(valueChanged (int)),SLOT(writeValue(int)));


The compiler is expecting to see a pointer-to QObject. The identifier MainWindow is the name of a class not an object of that class, you would be closer with w.g_sld (w is not a pointer so not w->g_sld).
The identifier g_sld is associated with a private member variable in the class MainWindow, and that is not accessible outside the class implementation.
The three argument connect() can only be used inside a QObject implementation because the target object is an implied "this".


Move the connect() into the MainWindow implementation. Usually in the constructor after the setupUi().

Radek
25th March 2014, 20:29
(1) If the UI file was created by Designer then g_sld is a pointer. See the ui_mainwindow.h file.
(2) I meant MainWindow, MyWindow is a typo.

Brixus
25th March 2014, 20:45
Thank you very much.

To solve the points 1 and 2 I tried the following:
I hope this is ok.

in mainwindow.h:

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
//g_sld to public
Ui::MainWindow *g_sld;
private:
Ui::MainWindow *ui;
};

and in mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myslots.h"
using namespace std;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QObject::connect(ui->g_sld, SIGNAL(valueChanged (int)),SLOT(mySlots::writeValue(int)));


}

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

Now I get a new error:


QObject::connect: No such slot MainWindow::writeValue(int) in ../EigenerSlot/mainwindow.cpp:10
QObject::connect: (sender name: 'g_sld')
QObject::connect: (receiver name: 'MainWindow')

I understand the error, but I dont know how to tell Qt the correct Slot.
I think this has maybe something to do with the third point I dont understand completely ;-)

ChrisW67
25th March 2014, 22:43
Line 9 in mainwindow.h is unnecessary. The variable g_sld already exists as a member of the Ui::MainWindow class pointed to by ui. It is that variable you access (correctly) as the signal source in your revised connect().

Your revised three-parameter connect() call can only connect to a slot in the same object. If writevalue() was a slot in the MainWindow class you would be good. To connect to a slot in another object you need the four parameter version where you specify the receiving object. In this case you need to have access to a pointer to the receiving object (you do not at the moment). Where is an instance of MySlots created?

Radek
26th March 2014, 05:37
A blackout on my side. I do apologize.


connect(w.ui->g_sld, ...);

MainWindow is a class name, not an instance name.

As to your last post, the same. You cannot connect to mySlots::writeValue() because nothing like that exists. mySlots is a class name not an instance name. You need to create an instance of mySlots (prior you connect) and connect to it. Remove the modifications from your last post, create an instance of mySlots prior MainWindow w; and connect in the MainWindow ctor (ui is private). If you do not want to connect in the ctor then make the pointer to the slider public:


class MainWindow : public QMainWindow
{
public :

QSlider *g_sld;

...
};

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
g_sld = ui->g_sld;
}

and connect elsewhere. Connect prior w.show();

Brixus
26th March 2014, 09:20
Oh my god.

This is all so complicated.

With creating an instance you mean that I have to use my function once without a signal, right?
So I would use it in main.cpp and just write writeVlaue(0);.

Acutally Ctors are quiet complicated for me at the moment.
I havent any idea how to build a constructor connection for my stuff.

So I would prefer the second solution.
Using your code

public :

QSlider *g_sld;

it tells me: 'QSlider' does not name a type.
I have tried several writings but nothing helped.
QObject is included.


And I sould connect in the main.cpp before w.show(), right?
If I try that I also get errors.
Replacing the ui in
QObject::connect(ui->g_sld, SIGNAL with "MainWindow" or with "w" doesent work.


Also if I try to use the function writeValue in main.cpp it does not work.

mySlots::writeValue(0);
It tells me: cannot call member function 'void mySlots::writeValue(int)' without object
I have no idea how to solve this.

Normally I have programmed in C and now C++ is so much more complicated...


It would be really nice if you could have a look to the file attached.
This is the programm shown in this thread.

I know its always the best to solve the own problems on its own, but at the moment I doubt that I am able to do that.

Therefore it would be very nice if you could fix my programm that I have a working sample to study how it works correctly.


Thank you very much for your help :-)

stampede
26th March 2014, 10:04
it tells me: 'QSlider' does not name a type.
Forward declare it :) Or include QSlider header file.

Therefore it would be very nice if you could fix my programm that I have a working sample to study how it works correctly.
You have plenty of such working samples in your Qt installation.

Oh my god.

This is all so complicated.
If you haven't already, please read this book:
http://www.smart2help.com/e-books/ticpp-2nd-ed-vol-one/Frames.html
without a C++ background you will struggle like that all the time.

Brixus
26th March 2014, 10:56
Thanks for your answer.


Forward declare it :) Or include QSlider header file.
The header file works ;)
I don't know how to declare in manually because I don't know on what QSlider is dependent.


You have plenty of such working samples in your Qt installation.
Really??? I have Ubuntu and if I search for QT examples I can't find anything.


If you haven't already, please read this book:
http://www.smart2help.com/e-books/ticpp-2nd-ed-vol-one/Frames.html
without a C++ background you will struggle like that all the time.

Thanks for the nice link.
You are completely right.
I also have a real book in my language here but also with this book it is quite hard.

For the moment I give up to solve my problem.
The connect still delivers only errors.

wysota
26th March 2014, 11:20
I also have a real book in my language here but also with this book it is quite hard.

It is not enough to have a book, you have to actually read it and do some exercises for it to help.

Radek
26th March 2014, 12:31
As far as C++ is concerned, I strongly recommend Bjarne Stroustrup, the C++ Programming Language, 4th. ed. Search the 4th edition especially, it is about C++11, the contemporary C++ norm. The preceding editions are also good books on C++ but they do not contain the todays C++. The book is on the web (a PDF file) but I do not know whether it is there legally, so that no link publicized on a well behaving forum :o Eckel is rather obsolete.

As to the basic problems. If you want a class, you need to specify it first (usually in a header file). You give the class a name (a class name):


class MainWindow : public QWindow
{
blah blah blah;
};

MainWindow is a class name. So far, there are no beasts of the MainWindow kind around. You need to create some if you want to work with them:


MainWindow w;

w is an instance of the class MainWindow. Now, you can reference w. You can call its methods, for example w.show(); or you can reference its data members, for example w.ui->g_sld; The instance is a real thing somewhere in the memory. You cannot write MainWindow.show() or MainWindow.ui->g_sld because MainWindow is only a tag (a type in C) and not something really existing.

When you create an instance of a class, the ctor (a constructor) will be called if there is some defined in the class. Before you reach the semicolon in


MainWindow w;

the ctor MainWindow::MainWindow() will be called. If there is no ctor, nothing will be done, only a memory for the instance will be reserved. Similarly, a dtor (a destructor) will be called when the instance is going to be removed (if it is going out of scope, if you are calling delete, or on return from a procedure).

In the ctor, you should do initializing of the instance. Clearing data members, setting pointers to something sensible and, in Qt, connecting the instance so that the instance can send or receive signals. You can do all this later of course but the ctor is a natural place where to initialize.

Note also, that the statements in your code are executed in the order you have written them. Therefore, if you want to connect a slider in a window class then you need:
(1) Create the window instance.
(2) Then create the slider instance, which is a child of the window. The window needs to exist if it should get any childs. In fact, the UI file will create the slider for you in ui->setupUi(this);
(3) Now, you connect the slider instance (ui->g_sld) to the window.

Brixus
26th March 2014, 12:31
It is not enough to have a book, you have to actually read it and do some exercises for it to help.

You are right.

I will give my best ;-)