Can Qt Signals Return a Value

Can Qt signals return a value?

OK. So, I did a little more investigating. Seems this is possible. I was able to emit a signal, and receive value from the slot the signal was connected to. But, the problem was that it only returned the last return value from the multiple connected slots:

Here's a simple class definition (main.cpp):

#include <QObject>
#include <QDebug>

class TestClass : public QObject
{
Q_OBJECT
public:
TestClass();

Q_SIGNALS:
QString testSignal();

public Q_SLOTS:
QString testSlot1() {
return QLatin1String("testSlot1");
}
QString testSlot2() {
return QLatin1String("testSlot2");
}
};

TestClass::TestClass() {
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1()));
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2()));

QString a = emit testSignal();
qDebug() << a;
}

int main() {
TestClass a;
}

#include "main.moc"

When main runs, it constructs one of the test classes. The constructor wires up two slots to the testSignal signal, and then emits the signal. It captures the return value from the slot(s) invoked.

Unfortunately, you only get the last return value. If you evaluate the code above, you'll get: "testSlot2", the last return value from the connected slots of the signal.

Here's why. Qt Signals are a syntax sugared interface to the signaling pattern. Slots are the recipients of a signal. In a direct connected signal-slot relationship, you could think of it similar to (pseudo-code):

foreach slot in connectedSlotsForSignal(signal):
value = invoke slot with parameters from signal
return value

Obviously the moc does a little more to help in this process (rudimentary type checking, etc), but this helps paint the picture.

Qt - Return value when signal is emitted?

You seem to be in a confusion. Even though signals in Qt can indeed return values, this is rarely used, if ever. Namely because it doesn't make a lot of sense.

What you probably want to do is not return but emit the image with a signal, this way you can connect it to a function that will receive the image and do something with it.

In that event, you want the signal to be declared as:

void downloaded(QImage img);

And emitted via:

emit downloaded(Image::fromData(fd->downloadedData()));

or just:

downloaded(Image::fromData(fd->downloadedData()));

as emit is just decoration for the sake of readability that doesn't do anything.

What I want to achieve is to create a function that return a QImage
from a QUrl [QImage func(QUrl)]. However I want to make sure that the
data has been downloaded before returning the value.

The only way this can happen is if you use a blocking API, but it is not recommended to do that in the main/GUI thread, as your application will appear to be non-responsive to the OS. You will have to do it in another thread and pass the end result to the main thread if you want to use the image in the GUI. At any rate, you will still have to use the above signal declaration that emits to image in order to get it there. When you make the connection to the main thread, Qt will detect that the two objects run in different threads and use a queued connection for you.

Or you can do a non-blocking implementation that runs periodically in the main thread without blocking it.

But the only way to get from an URL to an image in one function is to block the function with the data download.

How can I return a value from SLOT in Qt5?

I would just emit the data as a signal and wire up the connection between that new signal and a slot where you add then string to your ui.

A quick self-contained example (which btw. "Due to the length of the code I am not able to paste it here." is just an excuse, you can pretty much always cut down your relevant code)

Header:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextEdit>

class NetworkFile;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow(){}

public slots:
void addText(QString str)
{
edit->append(str);
}

private:
QTextEdit* edit;
NetworkFile* net;
};

class NetworkFile : public QObject
{
Q_OBJECT

public:
NetworkFile(QObject *parent = 0):
QObject(parent)
{
connect(&server, &QTcpServer::newConnection,
this, &NetworkFile::newConnection);
//TODO: check return value
server.listen(QHostAddress::Any,16001);
}

signals:
void dataRead(QString);

public slots:
void newConnection(){
//TODO: wire up socket disconnect with deleteLater, also check for null
QTcpSocket* socket = server.nextPendingConnection();
connect(socket, &QTcpSocket::readyRead,
this, &NetworkFile::dataAvailable);
}

void dataAvailable(){
//HACK: only for brevity, create a connection wrapper that contains the socket in real code
QTcpSocket* source = (QTcpSocket*)sender();

auto bytes = source->readAll();
if(bytes.size())
{
emit dataRead(QString(bytes));
}
}

private:
QTcpServer server;
};

#endif // MAINWINDOW_H

cpp file

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

MainWindow::MainWindow(QWidget *parent ):
QMainWindow(parent)
{
edit = new QTextEdit(this);
net = new NetworkFile(this);

connect(net, &NetworkFile::dataRead,
this, &MainWindow::addText );
setCentralWidget(edit);
}

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

return a.exec();
}

QT return value from a signal?

You should have a connection of type Qt::BlockingQueuedConnection when the emitter and receiver are in different threads.

So it should be like:

connect(this, SIGNAL(getUserNickS(QString)), dbtrad, SLOT(getUserNick(QString)),Qt::BlockingQueuedConnection);

When you emit your signal, it causes the current thread to block until the slot is returned.

What effect will exist when using any 'return' statement inside Qt's slot

None. The signals only invoke the function, if the function returns Qt will not use it.

On the other hand in Qt/PyQt it is said that a function is a slot if you use the decorator @QtCore.pyqtSlot(). In your case it is a simple function. Even so for a signal will not serve the data that returns the slot or function invoked.

Will this interruption have collision with the signal&slot mechanism?

No, it does not have a collision. Returning to the beginning, middle or end is irrelevant, remember every function returns something (if you do not use return the function will implicitly return None at the end).


On the other hand in a GUI the tasks of the functions must be light, if they are heavy you must execute it in another thread.

Qt: Return value of signal works, why is the official doc saying it is impossible / forbidden?

The problem is that the return types are are not checked for compatibility at connect-time, thus connecting a double-returning slot to a float-returning signal, say, will overflow the stack (no pun intended) space allocated to the float.

Is it possible to get a return value from a QRemoteObject Dynamic Replica slot?

For those who are looking for an answer on this, there is a way :) : the

QRemoteObjectPendingCall

undocumented argument.

bool success = QMetaObject::invokeMethod(_replica,"getName",Qt::DirectConnection,
Q_RETURN_ARG(QRemoteObjectPendingCall, call),
Q_ARG(QString, "id")
);
auto e = call.error();// , QRemoteObjectPendingCall::InvalidMessage);

call.waitForFinished();

//QVERIFY(call.isFinished());

qDebug() << QMetaType::typeName(call.returnValue().type());

QString retVal = call.returnValue().toString();

This is exactly the same kind a future object available for REPC Replica (except not templated)
No Documentation but there is some example in :
Qt Remote Objects integration tests

Sadly, there is currently (5.13.0) no way to get the pending reply in QML (QTBUG-77178) but Qt People are looking for it.



Related Topics



Leave a reply



Submit