Daniel Lee
Daniel Lee

Reputation: 215

update QT widget in c++11 thread

I'm using c++11 std::thread to make a request and response and then update QT lineedit with the response. I've read that updating QT widget from non-gui-thread is illegal. At some code, it just works fine. So I got to think that QThread can't update QT widget and c++11 thread is OK with it.

void MyWidget::on_button_clicked() {
    std::thread([this] {
        auto req = doSomeRequest();
        req.Wait();
        auto res = req.response();

        ui->lineedit->setText(res.name());
        // emit updateName(res.name());
    }).detach();
}

But another case, it gives me a segfault. Does anyone have I idea what's going on inside of QT?

PC: @     0x7f48d426bcda QFontEngineFT::loadGlyphSet()
*** SIGSEGV (@0x10) received by PID 5484 (TID 0x7f48e4f39780) from PID 16; stack trace: ***
    @     0x7f48dfde9390 (unknown)
    @     0x7f48d426bcda QFontEngineFT::loadGlyphSet()
    @     0x7f48d426bd39 QFontEngineFT::loadGlyphFor()
    @     0x7f48d426d2cf QFontEngineFT::lockedAlphaMapForGlyph()
    @     0x7f48e0a721a0 QRasterPaintEngine::drawCachedGlyphs()
    @     0x7f48e0a74a07 QRasterPaintEngine::drawTextItem()
    @     0x7f48e0a90905 (unknown)
    @     0x7f48e091e988 QTextLine::draw()
    @     0x7f48e091f79d QTextLayout::draw()
    @     0x7f48e11ce733 QWidgetLineControl::draw()
    @     0x7f48e1142e2b QLineEdit::paintEvent()
    @     0x7f48e1051b78 QWidget::event()
    @     0x7f48e11476f5 QLineEdit::event()
    @     0x7f48e100c52c QApplicationPrivate::notify_helper()
    @     0x7f48e1013220 QApplication::notify()
    @     0x7f48e0266ae0 QCoreApplication::notifyInternal2()
    @     0x7f48e104a54a QWidgetPrivate::sendPaintEvent()
    @     0x7f48e104ab5f QWidgetPrivate::drawWidget()
    @     0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104b71a QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104a702 QWidgetPrivate::drawWidget()
    @     0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104a702 QWidgetPrivate::drawWidget()
    @     0x7f48e104b8c4 QWidgetPrivate::paintSiblingsRecursive()
    @     0x7f48e104a702 QWidgetPrivate::drawWidget()
    @     0x7f48e101b891 (unknown)
    @     0x7f48e101baf1 (unknown)
    @     0x7f48e103ba7f QWidgetPrivate::syncBackingStore()
    @     0x7f48e1051c40 QWidget::event()
    @     0x7f48e100c52c QApplicationPrivate::notify_helper()
fish: “./aidmat ../aidmat.ini” terminated by signal SIGSEGV (Address boundary error)

Upvotes: 0

Views: 602

Answers (2)

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14688

What you do is undefined behavior due to the implementation of Qt. Implementation and behavior differs from platform to platform. The std::thread class is just a wrapper around system capabilities. The association between QThread and classes is part of Qt architecture about which standard library have nothing to do, so by using std::thread you just cheat to do what developers of Qt library told you that it should not be done.

If you need to do what you're trying, you should use signal-slot system.

Upvotes: 1

Benjamin T
Benjamin T

Reputation: 8321

It is illegal to update QWidgets from any thread but the main thread. The facts that it worked once using C++11 threads doesn't make it legal.

Try one of the following:

QMetaObject::invokeMethod(ui->lineedit, "setText", Q_ARG(QString, res.name());
// OR
QString name = res.name();
QTimer::singleShot(0, ui->lineedit, [name, this](){ui->lineedit->setText(name);});

Upvotes: 0

Related Questions