Signal to Slot in QT Creator, where is connect() function? - qt

In QT Creator, design mode, I right-click on a widget and select "Go to slot" and it creates a slot function for one of the widget's signals.
I would have thought that this would have generated a connect() function to create this connection, however, I can't find anything like that in any of the source code.
Where is the actual code that connects the widget's signal to the slot function?
thanks

If you're using QtCreator's Designer, one of the outputs from this is a .ui file
Qt Designer ui files are an XML representation of your form's widget tree, and are processed by uic, the "User Interface Compiler"
One of the features provided by Qt's ui format is AutoConnect.
uic automatically generates code in the form's setupUi() function to connect your signals and slots.
The way it works is as follows:
Your slots must conform to the following format:
void on_<object-name>_<signal-name>(<signal-parameters>);
where object-name is the name of the object which emits the signal this slot is for.
Later, uic then generates code which calls QMetaObject::connectSlotsByName(this);
Using Qt's reflection system, the QObject which has objectName()=object-name is found, and it's signal is connected to your slot.

Related

Assign new slot clicked() for button

I have copied several buttons in design form. As result all buttons got the same slot for clicked(). How to create and assign new personal slots for buttons?
UPD
Trying to use Signals & Slots editor. It was empty in the beginning, and I added new one:
But if I right click on button btnInfoCB->go to slot.. clicked() , it will point me to the same old method.
Qt creator will create slots for you. From designer, Right click on any push button and select 'Go to slots' option. select Clicked() signal press OK. Qt creator will navigate you to the created slot. Qt automatically connects your button clicked signal to the created slots.
You can do the same for all push buttons you created
Qt has an auto-connect feature that connects the slots named like this: on_UIELEMENTNAME_SIGNALNAME(SIGNAL_PARAMS) with the corresponding signal of the ui element, see the documentation here
So to fix this you have 2 options:
Option 1: rename the slots to have all the names corresponding with the names from .ui file:
private slots:
void on_MyFirstBtn_clicked();
void on_MySecondBtn_clicked();
//and so on
Or use option 2: manually connect
private slots:
//notice the prefix "on_" and the suffix "_clicked()" not part of the function name
void MyFirstBtnClicked();
void MySecondBtnClicked();
And in the constructor of the class (i named it MyWidget) add the connect calls:
connect(ui->MyFirstBtn, &QPushButton::clicked, this, &MyWidget::MyFirstBtnClicked);
connect(ui->MySecondBtn, &QPushButton::clicked, this, &MyWidget::MySecondBtnClicked);
LE: I don't recommend using the UI Designer for connecting slots that are defined in code because of maintainability reasons. That feature in Designer is very good if you need to connect already defined signals and slots, like check/unched to show/hide and other similar predefined functionality, but for your defined slots i don't like it.
New slot for an existing QPushButton /w auto connection
You have to change the objectName of QPushButton first. Then right click and create a new slot connection e. g. clicked(). Qt Creator will then create a new slot with the new objectName e. g. void on_newObjectName_clicked() { }. The old slot is no longer used then and you will get a new fresh function.
Manually connect /w signals and slots editor
If you like to connect it through your editor, you first have to click at the QWidget (e. g. MainWindow) and select change signals/slots from the menu. There you have to add a new function e. g. myNewSlot(), which is then available in the drop-down in the signals and slots editor as shown in your screenshot. If you use this type of connection you need to declare the slot in your .h in private slots and in the .cpp file. The object name may still link to an auto connection, so you probably need to change the objectName as well or remove the auto connected slot.

Qt Signals and Slots between Forms

How do I connect a Signal from a form to a Slot in another form? In other words I have a value that I am manipulating in a dialog.ui file that I want to emit to a slot that changes the value in the main application.
go to controller of the main GUI and connect both of them , like :
connect(form1,SIGNAL(increment()),form2,SLOT(manipulate()));
don't forget to use emit in the first form.

To access QML component in C++ backend

I have a qml file with Rectangle. I would like to trigger the onClicked( ) from C++ back-end.
So, How can I get access of QML component reference in C++/Qt backend?
You should use QObject::findChild() to locate the object, and simply invoke the signal as you would a nominal method.
But there is a catch, as QQuickRectangle itself is a private class, so it is not directly available for use in the C++ API. Also, it doesn't really have a clicked() signal, not unless you implemented one yourself. And if you did, it won't be part of the C++ interface.
Also, there is no onClicked() signal, the signal is clicked() and onClicked: is the handler hook.
However, you can still emit it using the Qt meta system, just use:
QObject * object = engine.rootObjects().at(0)->findChild<QObject *>("yourObjectName");
if (object) QMetaObject::invokeMethod(object, "clicked");
It will work even if the signal is implemented on the QML side, it will work even without casting to the concrete C++ type.
Now, if your object is not directly in the root object tree, you will not be able to find it and will have no choice but to pass a reference to it from the QML side to a C++ slot or invokable function.

Function connected to the button is called twice after one click

I have a problem with slots and signals. I created buttons and connected them to the clicked() slot. Then i decided to connect signals and slots manually and since then when I click the button it calls its function twice.
connect(ui->okButton, SIGNAL(clicked()), this, SLOT(on_okButton_clicked()));
void settingswindow::on_okButton_clicked()
{
qDebug() << "ok clicked";
this->close();
}
I was looking for the answer on google, but all i found was this: Where is the generated code of qt signals slots editor but my *.ui file looks like this: pastebin to the code. As you can see there's only one line with and nothing more. I can't find where the information about signals and slots is saved. Rebuild and clean options won't help.
This is not a bug in Qt. If you look at the generated code for your ui_*.h file, you'll notice that the last statement executed in the setupUi() function is a call to QMetaObject::connectSlotsByName().
Since your slot already conforms to the naming convention that this function is looking for, your slot is automatically connected to the signal.
By manually connecting the signal to the slot, in your settingswindow class, you effectively duplicate the connection.
As #Devopia mentioned, this is a documented feature.

SIGNAL & SLOT macros in Qt : what do they do?

I'm a beginner in Qt and trying to understand the SIGNAL and SLOT macros. When I'm learning to use the connect method to bind the signal and slot, I found the tutorials on Qt's official reference page uses:
connect(obj1, SIGNAL(signal(int)), obj2, SLOT(slot()))
However, this also works very well:
connect(obj1, &Obj1::signal, obj2, &Obj2::slot)
So what exactly do the macros SIGNAL and SLOT do? Do they just look for the signal in the class the object belongs to and return the address of it?
Then why do most programmers use these macros instead of using &Obj1::signal since the latter appears to be simpler and you don't need to change the code if the parameters of the signal function change?
The use of the SIGNAL and SLOT macros used to be the only way to make connections, before Qt 5. The connection is made at runtime and require signal and slots to be marked in the header. For example:
Class MyClass : public QObject
{
Q_OBJECT
signals:
void Signal();
slots:
void ASlotFunction();
};
To avoid repetition, the way in which it works is described in the QT 4 documentation.
The signal and slot mechanism is part of the C++ extensions that are provided by Qt and make use of the Meta Object Compiler (moc).
This explains why signals and slots use the moc.
The second connect method is much improved as the functions specified can be checked at the time of compilation, not runtime. In addition, by using the address of a function, you can refer to any class function, not just those in the section marked slots:
The documentation was updated for Qt 5.
In addition, there's a good blog post about the Qt 4 connect workings here and Qt 5 here.
Addition to the first answer.
what exactly did the macro SIGNAL and SLOT do
Almost nothing. Look at the qobjectdefs.h:
# define SLOT(a) "1"#a
# define SIGNAL(a) "2"#a
It just adds 1 or 2. It means that next code is valid and works as expected:
QObject *obj = new QObject;
connect(obj,"2objectNameChanged(QString)",this,"1show()");//suppose this is a pointer to a QDialog subclass
obj->setObjectName("newNAme");
why do most programmers use these macros instead of using like
&Obj1::signal
Because these macros work not only in Qt5.
Because with these macros there is no complexity with overloaded
signals (it can make your code very dirty and it is really not a simple thing)
Because with new syntax you sometimes need to use specific
disconnects
More details here.
To complete TheDarkKnight's answer, it is an excellent practice to refactor legacy code that is using the old Qt 4 SIGNAL and SLOT macros to Qt 5's new syntax using function address.
Suddenly, connection error will appear at compile time instead of at runtime! It's very easy to make a Qt 4 connection error as any spelling mistake will result in such an error. Plus, the name of the function must be the fully qualified name, i.e preceded with the full namespace if any.
Another benefit is the ability to use a lambda for the slot function, which can reduce need of a named function if the slot body is trivial.
These macros just convert their parameters to signal/slot-specific strings. The Differences between String-Based and Functor-Based Connections can be found in the docs. In short:
String-based:
Type checking is done at Run-time
Can connect signals to slots which have more arguments than the signal (using default parameters)
Can connect C++ functions to QML functions
Functor-based:
Type checking is done at Compile-time
Can perform implicit type conversions
Can connect signals to lambda expressions

Resources