I am trying to connect two slots with on signal. here is my header file where I have defined my signals
class loginChecker : public QObject
{
Q_OBJECT
public:
static loginChecker *instance(void);
signals:
void loginid();
void loginemail();
private:
loginChecker(void) {}
~loginChecker(void) {}
private:
static loginChecker *s_instance;
};
it is sigalton class. here is my slot which is another signalton class named as loginProcess
the slot name in this class in getUserData(QString& userData)
in The loginChecker.cpp
I am trying to connect these declared signals with getUserData(QString userData) slot
loginProcess *lp;
lp = loginProcess::instance();
here I am accessing instance of loginProcess signalton class which has slot
These are two ways I am trying to connect these signal and slot but none are working
QObject::connect(s_instance, SIGNAL(loginid()), es, SLOT(getUserData(userid)));
this is throwing no such slot error at runtime
`QObject::connect(s_instance, &esCoreAuthenticator::loginid, es, &loginProcess::getUserData(uid));`
this is thworing this error cannot call member function 'void loginProcess::getUserData(const QString&)' without object at compile time
Since your signal has no arguments you can't connect it to slot which has some.
And also it seems to me that in first case you should try SLOT(getUserData(QString&)) and in second case just &loginProcess::getUserData without any parenthesis.
Related
I'm using a DataRouter class to handle communication with a QSerialPort (and then communicate the results elsewhere). The connected device sends a status package every second or so, and I would like to read it without polling the device. I tried directly using QSerialPort's waitForReadyRead function, but no matter how long I set the wait time, it always timed out. Looking here and here I saw signals can be connected to Lambda functions. Now I'm trying to connect QSerialPort's readyRead signal to a Lambda which calls my on_dataRecieved function but I get the error C2665:"QObject::connect: none of the 3 overloads could convert all of the argument types. Below is an example of what I have:
DataRouter.h
template<class SerialPort>
class DataRouter
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
shared_ptr<SerialPort> m_port;
};
DataRouter.cpp
template<class SerialPort>
DataRouter<SerialPort>::DataRouter()
{
m_port = std::make_shared<SerialPort>()
QObject::connect(m_port, &QSerialPort::readyRead, this, [=](){this->on_dataRecieved();})
}
template<class SerialPort>
void DataRouter<SerialPort>::on_dataRecieved()
{
//Do stuff
}
If your "target" is not QObject you need to use the following overload of connect. The problem is that, you are trying to use non-QObject as "context" to determine the lifetime of the connection and that's not possible. To mitigate it you will need to release the connection somehow on DataRouter's destruction; one way is to store what connect() will have returned and call disconnect on it later on.
As for the signal coming from a smart pointer, have you tried this:
connect(m_port->get(), &QSerialPort::readyRead, &DataRouter::on_dataRecieved);
Your m_port is not entity of QSerialPort class, that's why you don't have QSerialPort::readyRead that can be emitted from it. template<class SerialPort> doesn't do what you what, it is just name of templated parameter.
You probably wanted something like this:
DataRouter.h
class DataRouter : QObject
{
public:
DataRouter ();
private slots:
on_dataRecieved();
private:
QSerialPort* m_port;
};
DataRouter.cpp
DataRouter::DataRouter()
{
m_port = new QSerialPort(this);
connect(m_port, &QSerialPort::readyRead, this, &DataRouter::on_dataRecieved);
// or connect(m_port, &QSerialPort::readyRead, this, [this](){this->on_dataRecieved();});
}
void DataRouter::on_dataRecieved()
{
//Do stuff
}
You don't have to wrap Qt classes in smart pointers as long, as you provide parent class for them. Memory freed when parent is destructed.
I have class
class Files : public QWidget
{
Q_OBJECT
public:
Files();
~Files();
public slots:
void saveFile(Ui::MainWindow * ui);
void openFile(Ui::MainWindow * ui);
void checkOpenFile(Ui::MainWindow * ui);
void newFile(Ui::MainWindow * ui);
void checkNewFile(Ui::MainWindow * ui);
void closeFile(Ui::MainWindow * ui);
};
and i want to connect button placed in MainWindow class with slot void newFile(Ui::MainWindow * ui) of Files class
i tried
files = new Files;
//files->newFile(ui); works as it should
connect(ui->actionExit, SIGNAL(triggered()), files, SLOT(closeFile(ui)));
and I have message:
QObject::connect: No such slot Files::closeFile(ui) in ../qt/src/core/mainwindow.cpp:16
QObject::connect: (sender name: 'actionExit')
How should i connect ui->actionExit with Files::closeFile(ui) slot the right way?
First, you are attempting to connect signal and slot which are not compatible with each other: closeFile slot requires a parameter of Ui::MainWindow * type but the signal which you are attempting to connect to it has no parameters.
Do you really need closeFile to take a pointer to Ui::MainWindow? Can you instead make this and other slots take no parameters? If you really need to access Ui::MainWindow from inside methods/slots within Files, you can just create a setter to pass the pointer to Ui::MainWindow to Files and use that pointer in slots which themselves won't take any parameters.
Second, you are trying to use old, obsolete and slow method of setting up connections between signals and slots. This method is not only bad because it's slow but it is also bad because it only shows you errors during runtime i.e. when you compile and launch your app. If you used pointer to member function based connection syntax, it would refuse to compile should you try to connect incompatible signals and slots. It is much better this way because you can see and fix the errors early.
I'm trying to write a method, with two parameters : the Q_PROPERTY name (char *) and the QObject * associated with, that permit to connect the notifySignal (if exists) of the Q_PROPERTY, to a void slot(QVariant), or to a slot dynamically builded which will call a void method(QVariant). The signature of the signal can vary according to the type of the parameter.
How can I achieve that in Qt 5? Maybe it's impossible, but I will not stop searching while I'm not sure of that.
So I think I have 3 solutions:
building dynamically a slot of the exact signature of the signal, from the signal name, and call a method(QVariant) in it, using the old Qt connect way:
connect(sender, SIGNAL (valueChanged(QString,QString)),
receiver, SLOT (updateValue(QString)) );
using the new Qt 5 connect system:
connect(sender, &Sender::valueChanged,receiver, &Receiver::updateValue );
building all slots signatures that can be used with QVariant.
Althougt, I don't know how to build a slot dynamically that call a specified method for the first solution ; I don't know how to retrieve the function pointer from the QMetaMethod of the notifySignal, for the second solution ; maybe the last solution is the best way, and easy to achieve, but it seams a bit extreme.
What do you think about it?
For "building a slot dynamically" there are private APIs in Qt (look for QMetaObjectBuilder or similar classes). However that doesn't solve the problem of the connection.
Note that QObject::connect is overloaded to take QMetaMethods as signals and slots. So you can easily build a "receiver" class object (for the only purpose of remembering which property it's acting upon):
class Receiver : public QObject {
Q_OBJECT
public:
explicit Receiver(const char *property, QObject *parent = 0)
: QObject(parent),
m_property(property)
{}
signals:
void propertyChangedForObject(const char *property, QObject *object);
public slots:
void onPropertyChanged() {
emit propertyChangedForObject(m_property, sender());
}
private:
const char * const m_property;
};
And hook it up in your method.
I have a problem creating a QPushButton and linking its signal to my slots. First, I created a class with the slot:
class A : public QWidget{
public slots:
void handleButton();
};
There is my handleButton function in the .cpp
void A::handleButton(int row, int col){
m_button->setText("Example");
// resize button
m_button->resize(100,100);
}
Then I want to connect the button.
QObject::connect(m_button, SIGNAL(clicked()), qApp, SLOT(handleButton()));
But I got an error when I start the application:
"No such slot"
Make sure that qApp is an object of class A (i.e. where your slot is defined).
That said, the signatures are wrong: a signal links to a slot only if the signature match
http://qt-project.org/doc/qt-4.8/signalsandslots.html
The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot.
And your slot hasn't the right signature:
http://qt-project.org/doc/qt-4.8/qabstractbutton.html#clicked
void QAbstractButton::clicked ( bool checked = false ) [signal]
You have a few errors in this code, if you define "void handlebutton()" then you must implement void handlebutton() NOT void handlebutton(inx x, int y) this code should not even compile.
More: in QT you CAN ONLY connect SIGNALS and SLOTS with the same parameters so you can connect SIGNAL(clicked()) with SLOT(handlebutton()) but not SIGNAL(clicked() with SLOT(handleButton(int, int)).
Another problem is that connect is executed at runtime so You must compile and run before Qt can show you the error.
So a possible solution is:
define and implement the slot void handlebutton() and connect that to the signal clicked(), then define another method handleButton (int x, int y) that you will call from inside handleButton().
I really hope that makes sense to you.
Your class definition should look like :
class A : public QWidget
{
Q_OBJECT
public slots:
void handleButton(int, int);
};
And you should connect it like:
QObject::connect(m_button, SIGNAL(clicked()),qApp, SLOT(handleButton(int a, int b)));
where a and b are variables for row and column.
This should work. Try understanding basic C++. :)
For just one class , i declare a slot and a signal , and in slot method definition i call signal method with emit keyword. But how can i emit signals with one class to another class which has a slot.
Well i try with a button to modify a label text. Button is created by A class (which must emit a signal) , and label is created by class B which must have a slot to modify text on it
It seems like you have class 1, which has a method that will be executed, and will call "emit". When that happens, the slot of another class will find out.
definition of 1st class:
class songs_text {
public:
signals:
void send_signal();
}
int songs_text:function() {
emit send_signal();
}
definition of class 2:
class wind {
public slots:
void continue_job() {
};
}
and your main program:
Wind wind();
Get_source songs_text(&mtempfile);
QObject::connect(&songs_text, SIGNAL(send_signal()),
&wind, SLOT(continue_job()));
Add a public method in the class named void emitSignalBlahBlah() to be a wrapper around the emit code. Then, all the other classes that need to fire this signal will access this object and call the method to do it.