Qt C++ 信号和槽没有触发

Posted

技术标签:

【中文标题】Qt C++ 信号和槽没有触发【英文标题】:Qt C++ signals and slots did not fire 【发布时间】:2014-05-27 16:20:25 【问题描述】:

我已经对 Qt 编程过几次,我非常喜欢信号和插槽功能。但是现在,我想当一个线程发出信号时我遇到了问题,另一个线程的相应插槽没有被触发。连接是在主程序中建立的。

这也是我第一次使用使用 CMake 的 Qt for ROS。 QThread 触发的信号触发了它们相应的槽,但我的类 UserInput 发出的信号没有触发它应该触发的 tflistener 中的槽。我已经尽我所能。有什么帮助吗?代码如下。

Main.cpp

#include <QCoreApplication>
#include <QThread>
#include "userinput.h"
#include "tfcompleter.h"
int main(int argc, char** argv)


    QCoreApplication app(argc, argv);

    QThread *thread1 = new QThread();
    QThread *thread2 = new QThread();
    UserInput *input1 = new UserInput();
    TfCompleter *completer = new TfCompleter();

    QObject::connect(input1, SIGNAL(togglePause2()), completer, SLOT(toggle()));
    QObject::connect(thread1, SIGNAL(started()), completer, SLOT(startCounting()));
    QObject::connect(thread2, SIGNAL(started()), input1, SLOT(start()));
    completer->moveToThread(thread1);
    input1->moveToThread(thread2);

    thread1->start();
    thread2->start();
    app.exec();
    return 0;

我想要做的是.. 有两个单独的线程。一个线程用于用户输入。当用户输入 [space] 时,线程会发出一个信号来切换另一个线程的布尔成员字段。另一个线程的任务是如果用户希望它运行则继续其进程,否则用户不希望它运行。我想授予用户在他想要的任何时候切换处理,这就是为什么我决定将它们带入单独的线程。

以下代码是tflistener和userinput。

tfcompleter.h

#ifndef TFCOMPLETER_H
#define TFCOMPLETER_H

#include <QObject>
#include <QtCore>

class TfCompleter : public QObject

    Q_OBJECT

private:
    bool isCount;

public Q_SLOTS:
    void toggle();
    void startCounting();

;

#endif

tflistener.cpp

#include "tfcompleter.h"
#include <iostream>

void TfCompleter::startCounting()

    static uint i = 0;

    while(true)
    
        if(isCount)
            std::cout << i++ << std::endl;

    

void TfCompleter::toggle()


//    isCount = ~isCount;
    std::cout << "isCount " << std::endl;


用户输入.h

#ifndef USERINPUT_H
#define USERINPUT_H

#include <QObject>
#include <QtCore>

class UserInput : public QObject

    Q_OBJECT

public Q_SLOTS:
    void start();   // Waits for the keypress from the user and emits the corresponding signal.

public:
Q_SIGNALS:
    void togglePause2();

;

#endif

用户输入.cpp

#include "userinput.h"
#include <iostream>
#include <cstdio>

// Implementation of getch
#include <termios.h>
#include <unistd.h>

/* reads from keypress, doesn't echo */
int getch(void)

    struct termios oldattr, newattr;
    int ch;
    tcgetattr( STDIN_FILENO, &oldattr );
    newattr = oldattr;
    newattr.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
    return ch;



void UserInput::start()


    char c = 0;
    while (true)
    
        c = getch();

        if (c == ' ')
        
            Q_EMIT togglePause2();
            std::cout << "SPACE" << std::endl;
        
        c = 0;
    

这里是 CMakeLists.txt。我也只是把它放在这里,因为我不知道 CMake 是否也有一个因素。

CMakeLists.txt

##############################################################################
# CMake
##############################################################################

cmake_minimum_required(VERSION 2.4.6)

##############################################################################
# Ros Initialisation
##############################################################################

include($ENVROS_ROOT/core/rosbuild/rosbuild.cmake)
rosbuild_init()
set(CMAKE_AUTOMOC ON)
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH $PROJECT_SOURCE_DIR/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH $PROJECT_SOURCE_DIR/lib)

# Set the build type.  Options are:
#  Coverage       : w/ debug symbols, w/o optimization, w/ code-coverage
#  Debug          : w/ debug symbols, w/o optimization
#  Release        : w/o debug symbols, w/ optimization
#  RelWithDebInfo : w/ debug symbols, w/ optimization
#  MinSizeRel     : w/o debug symbols, w/ optimization, stripped binaries
#set(ROS_BUILD_TYPE Debug)

##############################################################################
# Qt Environment
##############################################################################

# Could use this, but qt-ros would need an updated deb, instead we'll move to catkin
# rosbuild_include(qt_build qt-ros) 
rosbuild_find_ros_package(qt_build)
include($qt_build_PACKAGE_PATH/qt-ros.cmake)

rosbuild_prepare_qt4(QtCore) # Add the appropriate components to the component list here
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
##############################################################################
# Sections
##############################################################################

#file(GLOB QT_FORMS RELATIVE $CMAKE_CURRENT_SOURCE_DIR ui/*.ui)
#file(GLOB QT_RESOURCES RELATIVE $CMAKE_CURRENT_SOURCE_DIR resources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE $CMAKE_CURRENT_SOURCE_DIR FOLLOW_SYMLINKS include/rgbdslam_client/*.hpp)

#QT4_ADD_RESOURCES(QT_RESOURCES_CPP $QT_RESOURCES)
#QT4_WRAP_UI(QT_FORMS_HPP $QT_FORMS)
QT4_WRAP_CPP(QT_MOC_HPP $QT_MOC)

##############################################################################
# Sources
##############################################################################

file(GLOB_RECURSE QT_SOURCES RELATIVE $CMAKE_CURRENT_SOURCE_DIR FOLLOW_SYMLINKS src/*.cpp)

##############################################################################
# Binaries
##############################################################################

rosbuild_add_executable(rgbdslam_client $QT_SOURCES $QT_MOC_HPP)
#rosbuild_add_executable(rgbdslam_client $QT_SOURCES $QT_RESOURCES_CPP $QT_FORMS_HPP $QT_MOC_HPP)
target_link_libraries(rgbdslam_client $QT_LIBRARIES)

【问题讨论】:

首先,要查看的代码太多。您应该尝试缩小问题的范围以获得更好的帮助。第二,你说它不起作用...什么不起作用,你是怎么得出这个结论的? 【参考方案1】:

很难从您发布的代码中找到错误。我只想指出一个问题:

您首先建立连接,然后将对象移动到新线程。因为它们是在同一个线程中创建的,所以它们具有相同的Thread Affinity。所以默认情况下连接类型是direct,这意味着slot将在发出signal的同一个线程中执行。

但是在移动到新线程之后,两个对象的线程亲和性都发生了变化。虽然你没有说你怎么会发现它不起作用,但我建议你看看这个问题。如果您希望 slot 在不同的线程中执行,并以这种方式进行测试,那么您可能无法获得所需的输出并认为它不起作用。

signalslot打算在不同的线程中执行时,最好在将相应的对象移动到新线程后将它们连接起来。当对象在不同的​​线程中时,Qt::AutoConnection 默认使用Qt::QueuedConnection

【讨论】:

编辑了我的帖子。那么,当信号和槽处于不同的线程关联中时,如何连接它们呢?

以上是关于Qt C++ 信号和槽没有触发的主要内容,如果未能解决你的问题,请参考以下文章

QT学习之信号和槽

C++ ——Qt的信号和槽的详解

C++ ——Qt的信号和槽的详解

C++ GUI Qt的建立连接,信号和槽

Qt源码分析之信号和槽机制(QMetaObject是一个内部struct)

QT信号和槽