简体   繁体   English

QMetaObject :: invokeMethod()用于调用QListWidget :: addItem()时返回false

[英]QMetaObject::invokeMethod() returning false when used to call QListWidget::addItem()

I am trying to add an item to a QListWidget owned by the main thread from a background thread in a threadsafe manner by using QMetaObject::invokeMethod(). 我试图通过使用QMetaObject :: invokeMethod()以线程安全的方式将一个项目添加到后台线程从主线程拥有的QListWidget中。

QMetaObject::invokeMethod() works and returns true when I use it to call clear() on the QListWidget but returns false when I use it to call addItem(), as seen in this code: QMetaObject :: invokeMethod()可以正常工作,当我使用它调用QListWidget上的clear()时返回true,但是当我使用它调用addItem()时返回false,如以下代码所示:

void BlockingInvokeStringArg(QObject* widget, const char* functionName, const string& arg = "")
{
    QString argAsQString(arg.c_str());
    QGenericArgument genericArg = arg.empty() ? QGenericArgument() : Q_ARG(QString, argAsQString);
    if (!QMetaObject::invokeMethod(widget, functionName, Qt::BlockingQueuedConnection, genericArg))
    {
        throw runtime_error("QMetaObject::invokeMethod() returned false");
    }
}

void BacktestGui::on_buttonRunBacktest_clicked()
{
    auto runBacktest = [&]()
    {
        // Does not throw:
        BlockingInvokeStringArg(m_ui.listSymbols, "clear");
        // Throws:
        BlockingInvokeStringArg(m_ui.listSymbols, "addItem", "ItemName"); 
        // Does not throw but may be thread-unsafe due to a background thread interacting with a GUI component owned by the main thread:
        m_ui.listSymbols->addItem("ItemName");
    };
    QtConcurrent::run(runBacktest);
}

Why does QMetaObject::invokeMethod() return true when calling clear() on a QListWidget but return false when calling addItem()? 为什么在QListWidget上调用clear()时QMetaObject :: invokeMethod()返回true,而在调用addItem()时返回false?

If QMetaObject::invokeMethod() cannot be used to call addItem(), do you know a threadsafe alternative for adding an item to a QListWidget from a background thread? 如果QMetaObject :: invokeMethod()无法用于调用addItem(),您是否知道从后台线程向QListWidget添加项目的线程安全替代方法?

invokeMethod() is able to invoke a signal or a slot. invokeMethod()能够调用信号或插槽。 QListWidget::clear() is a slot, so that works. QListWidget :: clear()是一个插槽,因此可以正常工作。 QListWidget::addItem() is not a slot, therefore you can't invoke it. QListWidget :: addItem()不是插槽,因此您不能调用它。

The solution is simple. 解决方案很简单。 Write a slot that takes the QListWidget as an argument and which calls addItem() on it, and invoke that slot. 编写一个使用QListWidget作为参数并在其上调用addItem()的插槽,然后调用该插槽。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM