简体   繁体   English

Qt C ++信号和插槽未触发

[英]Qt C++ signals and slots did not fire

I have programmed Qt a couple of times already and I really like the signals and slots feature. 我已经对Qt进行了几次编程,我真的很喜欢信号和插槽功能。 But now, I guess I'm having a problem when a signal is emitted from one thread, the corresponding slot from another thread is not fired. 但是现在,我想当一个线程发出信号时,另一个线程的相应插槽未触发时,我遇到了问题。 The connection was made in the main program. 连接是在主程序中进行的。

This is also my first time to use Qt for ROS which uses CMake. 这也是我第一次将Qt用于使用CMake的ROS。 The signal fired by the QThread triggered their corresponding slots but the emitted signal of my class UserInput did not trigger the slot in tflistener where it supposed to. QThread发出的信号触发了它们相应的插槽,但是我的类UserInput发出的信号并未触发tflistener中的插槽,应该触发该插槽。 I have tried everything I can. 我已经尽力了。 Any help? 有什么帮助吗? The code is provided below. 下面提供了代码。

Main.cpp 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;
}

What I want to do is.. There are two seperate threads. 我想做的是..有两个单独的线程。 One thread is for the user input. 一个线程供用户输入。 When the user enters [space], the thread emits a signal to toggle the boolean member field of the other thread. 当用户输入[space]时,线程将发出信号以切换另一个线程的布尔成员字段。 The other thread 's task is to just continue its process if the user wants it to run, otherwise, the user does not want it to run. 另一个线程的任务是,如果用户希望其运行,则仅继续其进程,否则,用户不希望其运行。 I wanted to grant the user to toggle the processing anytime that he wants, that's why I decided to bring them into seperate threads. 我想授予用户在他希望的任何时间切换处理的功能,这就是为什么我决定将它们引入单独的线程中的原因。

The following codes are the tflistener and userinput. 以下代码是tflistener和userinput。

tfcompleter.h 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 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;

}

UserInput.h UserInput.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

UserInput.cpp UserInput.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;
    }
}

Here is the CMakeLists.txt. 这是CMakeLists.txt。 I just placed it here also since I don't know maybe the CMake has also a factor here. 我也把它放在这里,因为我不知道CMake在这里也有影响。

CMakeLists.txt 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})

It is hard to find bug from your posted code. 从您发布的代码中很难找到错误。 I just want to point out one issue: 我只想指出一个问题:

You are first making the connection and then moving the objects to new threads. 您首先要建立连接,然后将对象移动到新线程。 Since they were created in same thread they had same Thread Affinity . 由于它们是在同一线程中创建的,因此它们具有相同的Thread Affinity So by default the connection type will be direct , which means, the slot will be executed from the same thread from which signal is emitted. 因此,默认情况下,连接类型为direct ,这意味着slot将在发出signal的同一线程中执行。

But after moving to new threads, thread affinity for both objects gets changed. 但是,在移到新线程之后,两个对象的线程亲和力都会更改。 Although you did not say how you could find out it is not working, I recommend to look at this matter. 尽管您没有说出如何发现它不起作用,但我建议您看一下这件事。 If you expect the slot to be executed in different thread, and tested that way, then you may not get desired output and think it is not working. 如果您希望slot在不同的线程中执行并以这种方式进行测试,那么您可能不会获得所需的输出并认为它不起作用。

When signal and slot are meant to be executed in different thread, it is better to connect them after moving the corresponding objects to new threads. signalslot要在不同的线程中执行时,最好将相应的对象移动到新线程后再连接它们。 Qt::AutoConnection will by default use Qt::QueuedConnection when objects are in different thread. 默认情况下,当对象位于不同线程中时, Qt::AutoConnection将使用Qt::QueuedConnection

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

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