Signals Slots and Class Pointers
Hi guys, this is more of a class pointer and C++ but anyway. I created a window with a widget in Qt and also added a horizontal slider widget to the main window as well. My widget is an OpenGL widget and I want to be able to control an object in the OpenGL window using the slider. I went into the default constructor of the window and added the connect code:
Code:
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), *GLWidget, SLOT(setAngle int angle))
However I'm not really familiar with class pointers in projects with multiple files (very confused as to which files are accessed first, which second when the main window pops up and calls subsequent stuff). My understanding is that to use a class pointer, you need to first create the class pointer and assign a value to it just like any other pointer. However, in my case, I'm trying to send a value from my slider widget to an object which should already exist? Simply writing *GLWidget in the connect function doesn't seem to be able to have the program recognise the existence of my GLWidget - I don't get the auto pop up of the available slots for my GLWidget class i.e.
Code:
SLOT(... nothing pops up)
Re: Signals Slots and Class Pointers
You are correct, this is a C++ question.
A class is a definition of a thing. An object is one, possibly among many, of those things. A pointer is the address of an object not a class: i.e. "class pointer" makes no sense. The QObject::connect() call requires pointers to sender and receiver objects. You are responsible for creating the object and providing the pointer to it. You can create objects as local variables (on the stack) or on in allocated memory (on the heap):
Code:
class Foo {
public:
...
int value;
void doStuff() { }
...
};
void somefunc(const Foo &f) {...}
void otherfunc(Foo *f) {...}
Foo foo; // an object of class Foo on the stack
Foo *bar; // a pointer to an object of class Foo. The object dos not exist yet.
bar = new Foo; // now it does
Foo *baz = &foo; // a pointer to an object of class Foo, pointing at the same object as foo.
// Using the Foo objects
foo.doStuff();
bar->doStuff();
somefunc(*bar); // Supply the object pointed to by bar
otherfunc(bar); // Supply the pointer to an object
otherfunc(&foo); // Supply the pointer to the object foo
delete bar; // free the allocated memory
Objects are created in the order your code creates them, and the do what your code commands of them. Its irrelevant what file contains which class definition: classes don't do anything until you create an object or objects based on them.
In your code ui->horizontalSlider is a pointer to an object of the QSlider class. How have you created your GLWidget object, or is GLWidget the name of the class?
Re: Signals Slots and Class Pointers
Quote:
Originally Posted by
ChrisW67
You are correct, this is a C++ question.
Objects are created in the order your code creates them, and the do what your code commands of them. Its irrelevant what file contains which class definition: classes don't do anything until you create an object or objects based on them.
In your code ui->horizontalSlider is a pointer to an object of the QSlider class. How have you created your GLWidget object, or is GLWidget the name of the class?
Yep I understand. The bit I don't get is that when I look under main.cpp, I can clearly see my main window object being created and called 'w'. After that, I don't see where my GLWidget gets created other than seeing the .ccp code and .h head files for it and know that it works when I run the application after compilation... so it's getting called somewhere, but no idea where... hence the confusion as to what get's called in what order.
Quote:
Originally Posted by
ChrisW67
How have you created your GLWidget object, or is GLWidget the name of the class?
It's the class itself.
Re: Signals Slots and Class Pointers
Quote:
Originally Posted by Atomic_Sheep
It's the class itself.
That won't work.
If you have put a widget of class GLWidget into a Designer UI (using the promotion feature) then the code generated from the .ui file (e.g. ui_mainwindow.h) is creating an object of that class during the setupUi() call you see in widget class constructors. A pointer to such an object will be accessible through the ui pointer just like the slider. I suggest you open the ui_mainwindow.h file and read it to get a better understanding.
If you are not using Designer then I'll quote myself:
Quote:
Originally Posted by Me
You are responsible for creating the object and providing the pointer to it. You can create objects as local variables (on the stack) or on in allocated memory (on the heap):
Re: Signals Slots and Class Pointers
Quote:
Originally Posted by
ChrisW67
That won't work.
A pointer to such an object will be accessible through the ui pointer just like the slider.
Of course! Thanks, pretty sure I'll be able to get it to work now...
Re: Signals Slots and Class Pointers
Nope, looks I'm too stupid to figure this one out, after spending a few hours on this, I still can't get it to work.
I've got the two classes (mainwindow and glwidget)... in the mainwindow class constructor I've connected:
Code:
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->widget, SLOT(...);
However as the ... indicates... no slots from my glwidget class pop up.
The glwidget and mainwindow are two seperate classes with their own .h and .cpp files and I've definitely added the includes but still no luck.
I added a label to my ui and connected that to the horizontalslider and the label shows the values no problems and also pops up with "setNum(int)" when I'm typing up the connect command...
Code:
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->label, SLOT(setNum(int)));
I've also written the code for my slot in my glwidget.cpp file:
Code:
void GLWidget::SetValue(int Value)
{
if (Value != m_Value)
{
m_Value = Value;
}
}
But still no luck.
Re: Signals Slots and Class Pointers
The fact that Creator does not recognize your slot, doesn't mean you can't use it. Just type in the slot signature manually. And make sure you really declared the function to be a slot.
Re: Signals Slots and Class Pointers
I was wondering whether this might be the case so I tried what you suggested but the implementation of my receiving objects slot doesn't appear to be registering because my opengl's object rotation doesn't appear to be happening. I put a messagebox inside my slot implementation and it doesn't pop up as I move the slider about... the value in the label changes though.
Re: Signals Slots and Class Pointers
We'd have to see your actual code as currently with those little pieces you posted it is hard to tell anything. In general you need your method to be declared as a slot and you need to be passing a pointer to an instance of that class to the connect() statement to be able to connect to the slot.
Re: Signals Slots and Class Pointers
Also look at the debug output of your program for warnings of the type:
Code:
QObject::connect: No such
slot GLWidget
::SetValue(int)
indicating that the SetValue() function is not declared as a slot. The glwidget.h file should look like:
Code:
...
class GLWidget: public ...
{
Q_OBJECT
public:
GLWidget(...);
...
public slots: // <<<< this
void SetValue(int value);
...
};
...
and be included in the PRO file HEADERS variable.
Re: Signals Slots and Class Pointers
Looks like HEADERS in pro are fine.
As for the code...
mainwindow.h
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "glwidget.h"
namespace Ui {
class MainWindow;
}
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
int m_Angle;
void AngleUpdate(int m_Angle);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
glwidget.h
Code:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QtOpenGL/QGLWidget>
#include <cmath>
#include "mainwindow.h"
#include <QMessageBox>
{
Q_OBJECT
public:
explicit GLWidget
(QWidget *parent
= 0);
int m_Angle;
void initializeGL();
void paintGL();
void resizeGL(int w, int h);
public slots:
void SetAngle(int Angle);
};
#endif // GLWIDGET_H
mainwindow.cpp
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow
::MainWindow(QWidget *parent
) : ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->Widget, SLOT(SetAngle(int Angle))); //Widget is just the standard widget which I've promoted to GLWidget in form editor
connect(ui->horizontalSlider, SIGNAL(valueChanged(int)), ui->label, SLOT(setNum(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
glwidget.cpp
Code:
#include "glwidget.h"
GLWidget
::GLWidget(QWidget *parent
) :{
}
void GLWidget::SetAngle(int Angle)
{
if (Angle != m_Angle)
{
m_Angle = Angle;
QMessageBox::information(0,
"inside slot",
"inside slot");
}
}
P.S. There might be one or two mistakes here or there e.g. m_Angle used instead of Angle or something like that... I'm 99% sure I don't have that mistake in my actual program.
Re: Signals Slots and Class Pointers
In the last few posts the slot has been referred to as SetNum(), SetValue(), and now SetAngle(). I asked you to check for run time error messages like:
Code:
QObject::connect: No such
slot GLWidget
::SetAngle(int Angle
)
Line 9 of mainwindow.cpp is probably generating one because the slot signature is incorrect. You do not include the argument names in the signal or slot signatures.
Re: Signals Slots and Class Pointers
Forgot to say that yes I did check for those errors, I didn't see any, but I just realised that run-time errors are under "Application Output" and yes it's spitting out the "no such slot" error. i.e. :
Object::connect: No such slot GLWidget::SetAngle(int Angle) in ...\MainWindow.cpp:9
Object::connect: (sender name: 'horizontalSlider')
Object::connect: (receiver name: 'Widget')
...exited with code 0
I used different names for my slots previously because I was simply typing the code up as I was writing up the message. In the latest iteration it was copy paste with some minor editing, but the latest code that I provided should have all the naming issues sorted out.
Re: Signals Slots and Class Pointers
Still unable to get my signals and slots to work :(.
my .cpp files are :main.cpp, button.cpp, mainWindow.cpp and mainWindowWidget.cpp.
mainWindowWidget.cpp has the following signal:
Code:
void mainWindowWidget
::mousePressEvent(QMouseEvent *event
) {
if(event->button() == Qt::LeftButton) //left mouse button - need to check this.
{
cMousePositionAtClick = event->pos();
emit MouseClickLocation(cMousePositionAtClick);
//QMessageBox::information(this, "Mouse Click Detected", "Mouse Click Detected");
}
}
I have a slot in my button.h and its implementation.
here's the code in main.cpp:
Code:
mainWindow w;
Button button1(0,0,50,50);
connect(w,
SIGNAL(MouseClickLocation
(QPoint)), button1,
SLOT(LocationGrabber
(QPoint)));
w.show();
However when I compile it I get the following errors:
main.cpp:11: error: cannot convert 'mainWindow' to 'SOCKET' for argument '1' to 'int connect(SOCKET, const sockaddr*, int)'
Re: Signals Slots and Class Pointers
Two basic C++, not Qt, problems:
The error message tells you that the compiler has found only function 'int connect(SOCKET, const sockaddr*, int)' when trying to compile line 11 (I assume line 3 of your posted snippet). The arguments you have given cannot be coerced into the arguments required by that function so it fails. You want QObject::connect() and you cannot access that as an unqualified name outside of the implementation of a QObject sub-class. Use the static QObject::connect() function.
QObject::connect() requires a pointer to an object, i.e. &w and &button1, not the actual objects as you are current trying to do.
Re: Signals Slots and Class Pointers
Deleted... figured it out.
Re: Signals Slots and Class Pointers
Thanks Chris for helping out with the previous problem.
Another question. In the Qt example with the spinning boxes:
Code:
Window::Window()
{
for (int i = 0; i < NumRows; ++i) {
for (int j = 0; j < NumColumns; ++j) {
clearColor.setHsv(((i * NumColumns) + j) * 255
/ (NumRows * NumColumns - 1),
255, 63);
glWidgets[i][j] = new GLWidget(0, 0);
glWidgets[i][j]->setClearColor(clearColor);
glWidgets[i][j]->rotateBy(+42 * 16, +42 * 16, -21 * 16);
mainLayout->addWidget(glWidgets[i][j], i, j);
connect(glWidgets[i][j], SIGNAL(clicked()),
this, SLOT(setCurrentGlWidget()));
}
}
The code creates glWidget objects for each of the cubes to spin. I just have:
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
{
ui->setupUi(this);
}
mainwindow::~mainwindow()
{
delete ui;
}
and a .cpp file for mainwindowGLWidget.
I'm trying to connect a signal from another class to a slot of my mainwindowGLWidget class, however I don't know the name of the object of my mainwindowGLWidget class. How do I find this out?
My limited understanding is that when the compiler runs, ?moc? generates the ui.h file in the -build-desktop folder? But does this somehow solve my problem?
I know it says this in relation to my glwidget...
widget = new MyOpenGLWidget(centralWidget);
1 Attachment(s)
Re: Signals Slots and Class Pointers
uic generates the ui_stuff.h file from your stuff.ui file.
The name of the variable holding a pointer to your custom widget is set by you in Designer and carried over into generated UI code. In Designer:
Attachment 8193
and in the generated code is the class that the ui pointer points to an instance of:
Code:
#include <QtGui/QButtonGroup>
#include <QtGui/QFrame>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QFrame *myCustomFrame;
// <<<<< here
{
...
// <<<< and here
myCustomFrame
= new QFrame(Form
);
myCustomFrame
->setObjectName
(QString::fromUtf8("myCustomFrame"));
myCustomFrame
->setFrameShape
(QFrame::Box);
...
} // setupUi
...
};
...
#endif // UI_UNTITLED_H
so in your code you can access it through the ui pointer thus:
Re: Signals Slots and Class Pointers
Thanks Chris... had to reread this whole thread a few times to pick out to what information I applied the principle of 'selective hearing'. Finally got everything to work as desired! Now comes the fun task of fixing the next problem caused by the solving of the old prob :). Thanks again.