C++ Qt线程使用从工作线程到gui的信号/插槽时出现故障

C++ Qt线程使用从工作线程到gui的信号/插槽时出现故障,c++,qt,qthread,C++,Qt,Qthread,我有一个Qt应用程序,它是使用Qt Creator及其附带的GUI工具开发的。我有一个主线程,TheGui和一个由主线程创建的工作线程,WorkerThread(称为thread) 我遇到的问题是,当我使用 公共插槽: void updateTable(字符串str); 在GUI的头文件和信号void sendList(string str)中在工作线程的头文件中,永远不会调用插槽。我用计算机把两者连接起来 connect(&thread),信号(sendList(string str), 这

我有一个Qt应用程序,它是使用Qt Creator及其附带的GUI工具开发的。我有一个主线程,
TheGui
和一个由主线程创建的工作线程,
WorkerThread
(称为
thread

我遇到的问题是,当我使用

公共插槽:
void updateTable(字符串str);
在GUI的头文件和信号
void sendList(string str)中在工作线程的头文件中,永远不会调用插槽。我用计算机把两者连接起来

connect(&thread),信号(sendList(string str),
这个,SLOT(updateTable(stringstr));
在GUI cpp文件的构造函数中。除了工作线程中的插槽和GUI中的信号外,我做了一些类似的事情,它工作得很好。通过使用调试器,我知道信号发送列表确实被调用了,只是永远不会进入它


有什么想法吗?

确保连接确实建立了吗?如果连接调用有任何问题,通常会在
cerr
上显示一些关于它的调试输出

其次,我认为您有一个输入错误——若您从代码中复制了connect调用,那个么您就知道信号周围缺少括号——应该是

connect(&thread,SIGNAL(sendList(string)),this,SLOT(updateTable(string));

第三,您作为信号/插槽参数传递的是什么?它是std::string吗?线程之间的连接必须是队列连接。队列连接只能使用宏声明并注册的类型作为参数。据我所知,Qt默认情况下不会声明
std::string
,因为它更喜欢
QString
。如果没有将这些添加到代码中,则可能是失败的原因。

是否确实建立了连接?如果connect调用出现任何问题,通常会在
cerr
上对其进行一些调试输出

其次,我认为您有一个输入错误——若您从代码中复制了connect调用,那个么您就知道信号周围缺少括号——应该是

connect(&thread,SIGNAL(sendList(string)),this,SLOT(updateTable(string));
第三,您作为信号/插槽参数传递的是什么?它是std::string吗?线程之间的连接必须是队列连接。队列连接只能使用宏声明并注册的类型作为参数。据我所知,Qt默认情况下不会声明
std::string
,因为它更喜欢
QString
。如果您没有将这些添加到代码中,则可能是失败的原因

  • 由于信号和插槽位于不同的线程上,因此它们之间的连接具有
    Qt::QueuedConnection
    类型。对于排队连接,Qt必须能够保存信号参数的副本,以便稍后将其传递到插槽。
    因此,要通知Qt该类型是可复制的,您必须将其注册到Qt的元对象系统(请参阅),如下所示:

    // This macro call should be put in one of your .h files 
    Q_DECLARE_METATYPE(std::string)
    
    // You should call this function before any (queued) 
    // signal/slot connection involving the type
    qRegisterMetaType<std::string>();
    
  • 您还可以使用已注册的
    QString
    QByteArray
    ,而不是
    std::string
    ,因为这些函数是插槽和信号,因此已经是特定于Qt的

  • 由于信号和插槽位于不同的线程上,因此它们之间的连接具有
    Qt::QueuedConnection
    类型。对于排队连接,Qt必须能够保存信号参数的副本,以便稍后将其传递到插槽。
    因此,要通知Qt该类型是可复制的,您必须将其注册到Qt的元对象系统(请参阅),如下所示:

    // This macro call should be put in one of your .h files 
    Q_DECLARE_METATYPE(std::string)
    
    // You should call this function before any (queued) 
    // signal/slot connection involving the type
    qRegisterMetaType<std::string>();
    

  • 您也可以使用已注册的
    QString
    QByteArray
    ,而不是
    std::string
    ,因为这些函数是插槽和信号,因此已经是Qt特定的。

    请参阅感谢您的响应!我目前实际上是通过使用指针解决了这个问题。我应该在哪里调用qRegisterMetaType?我一直从int qMetaTypeId(T*)[使用T=StringVector]实例化错误''我想声明的是StringVector。@Kyle可能您没有在.cpp文件中包含使用Q_declare_元类型的头文件,您在该文件中调用了qRegisterMetaType。头文件中是否需要放置它?在Q_对象下?此外,我已经切换到使用QVector并使用插槽传递它。基于文档我一直在看的选项,这也不是自动注册的?Q_DECLARE_元类型应该在任何类声明之外。你可以使用
    QStringList
    来代替应该注册的。问题是我需要在<和qRegisterMetaType内的类型之间留一个空格,并将宏保持在类声明之外开始。现在一切都好了!感谢您的回复!我实际上暂时通过使用指针解决了这个问题。我应该在哪里调用qRegisterMetaType?我一直从“int qMetaTypeId(T*)[with T=StringVector]实例化错误”'我想声明的是StringVector。@Kyle可能您没有在.cpp文件中包含使用Q_declare_元类型的头文件,您在该文件中调用了qRegisterMetaType。头文件中是否需要放置它?在Q_对象下?此外,我已经切换到使用QVector并使用插槽传递它。基于文档我一直在看的选项,这也不是自动注册的?Q_DECLARE_元类型应该在任何类声明之外。你可以使用
    QStringList
    来代替应该注册的。问题是我需要在<和qRegisterMetaType内的类型之间留一个空格,并将宏保持在类声明之外好了,现在一切都好了!