Вопрос

I'm trying to use signals and slots to pass information to the GUI thread from another thread, as I can't modify a pixmap from any other thread. I'm encountering a runtime error:

Object::connect: No such signal QThread::image_change(std::string) in visualiser.cpp:33

Judging from this, though I may be wrong, it looks like the signal is being searched for in the wrong namespace, as it is actually defined in Visualiser::image_change().

My code is as follows:

Visualiser.cpp:

    QFutureWatcher<void> watcher;
    connect(watcher.thread(), SIGNAL(image_change(std::string)), QCoreApplication::instance()->thread(), SLOT(update_image(std::string)), Qt::QueuedConnection);
    QFuture<void> update_thread = QtConcurrent::run(this, &Visualiser::update_state);
    watcher.setFuture(update_thread);

   ...

    emit(image_change(imageSrc));

   ...

    void Visualiser::update_image(std::string src)
{
    QImage image;
    image.load(src.c_str());
    ui->visualContainer->setPixmap(QPixmap::fromImage(image));
}

visualiser.h:

    signals:
    void image_change(std::string src);

public slots:
    void update_image(std::string src);
Это было полезно?

Решение 2

The source and the target of the connection are the same object, this, so the connect call should be:

connect(this, SIGNAL(image_change(std::string)), this, SLOT(update_image(std::string)));

Since the signal will be emitted from another thread than the one the Visualizer has an affinity with (see QObject::moveToThread()), the connection with the slot will automatically be queued, and the slot will be executed by the correct thread.

But for queued connection to work, Qt has to store temporarily the parameter until it can actually call the slot, which is done by converting it to QVariant, storing it somewhere, and then reconverting it to the actual type when the receiving thread is ready to execute the slot.

So you need to register std::string to Qt's metatype system with Q_DECLARE_METATYPE or change the signal and slot parameter type to one that is already registered to (like QString or QByteArray).

Другие советы

Don't pass thread pointers into connect - pass pointers to the sender and receiver of the event (like this). Because you're giving it QThread pointers instead, Qt is looking for those signals and slots in QThread, where they don't exist. If you give it Visualizer pointers instead, Qt will look for those functions in Visualizer, where they really are, and everything will work.

Hope that helps!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top