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

标签 c++ qt signals-slots

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

这也是我第一次使用 Qt for ROS,它使用 CMake。 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] 时,该线程会发出一个信号来切换另一个线程的 bool 成员字段。另一个线程的任务是在用户希望它运行时继续其进程,否则,用户不希望它运行。我想允许用户在他想要的任何时候切换处理,这就是为什么我决定将它们带入单独的线程。

以下代码是 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($ENV{ROS_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})

最佳答案

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

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

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

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

关于c++ - Qt C++ 信号和槽没有触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23894339/

相关文章:

c++ - 信号与信号2

listview - 如何在 QML 中的 ListView 中绑定(bind)到来自委托(delegate)组件的信号

c++ - 运算符重载 ("<<") :why the “cout” did not work properly?

QT5 和 SQLite3 "No query Unable to fetch row"

c++ - 使用单色 QImage

c++ - 在 QScrollBar 可见性发生变化时获取 QScrollBar 宽度

c++ - 如何在构造函数中限制字符数组长度

c++ - 选中多个项目时如何清除QListView的选择?

C++ QT OSX Qt::META+Qt::Key_Tab 快捷键绑定(bind)

c++ - 将事件传播到 QGraphicsView 和 QGraphicsScene