QT信号&插槽,插槽未在信号发射时调用

发布于 2025-01-25 14:31:58 字数 6647 浏览 2 评论 0原文

我一直在遇到这个问题已有几周了,但在任何地方都没有找到解决方案。我竭尽所能找到问题,一切看起来都不错,但由于某种原因,它不起作用。 我测试了loginfailed()信号和handleloginfailed()插槽之间的连接,它返回了,打印了对象信息,它显示了连接。尝试了不同的QT ::连接类型,没有任何可用。

这两个对象被定义为波纹管。

loginService.h

#ifndef LOGINSERVICE_H
#define LOGINSERVICE_H

#include <QObject>
#include <QVariant>
#include "libs/qubeapi/QubeAPI.h"
#include "libs/qubeapi/LoginCommand.h"
#include "libs/qubeapi/APIBridge.h"
#include "libs/mge-users/User.h"
#include "libs/mge-users/permissionfactory.h"
#include "Utils/serverstate.h"
#include "Utils/singleton.h"
#include "Utils/baseservice.h"
class LoginService : public QObject
{
    Q_OBJECT
    QubeAPI* api;
    APIBridge* bridge;
    LoginCommand* loginCmd;
    QString m_userType;

    QString m_firstName;

    QString m_lastName;

    User *m_user;

public:
    explicit LoginService(QObject *parent = nullptr);
    Q_PROPERTY(QString userType READ userType WRITE setUserType NOTIFY userTypeChanged)
    Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY firstNameChanged)
    Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged)
    Q_PROPERTY(User* user READ user WRITE setUser NOTIFY userChanged)
    const QString &userType() const;
    void setUserType(const QString &newUserType);

    const QString &firstName() const;
    void setFirstName(const QString &newFirstName);

    const QString &lastName() const;
    void setLastName(const QString &newLastName);

    User *user() const;
    void setUser(User *newUser);


signals:
    void success(QString token);
    void loginFailed();
    void userTypeChanged();
    void firstNameChanged();
    void lastNameChanged();
    void staffLogout();
    void userTypeRecived();
    void userChanged();

public slots:
    void requestLogin(QString userName, QString password);
    void loginResponse(QString jsonData);
    void doClose();

    void prepareGetUserType();
    void loadUserType(QString jsonData);




};

#endif // LOGINCONTROLLER_H

发出信号的函数:

void LoginService::loginResponse(QString jsonData)
{

    QSignalSpy spy(this,SIGNAL(loginFailed()));
    if(jsonData == "") {
        emit Singleton<ServerState>::GetInstance().offlineServer();
        return;
    }
    QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
    QString token = doc["data"]["tokenAuth"]["token"].toString();

    if(!token.isEmpty()) {
        UserSession::getInstance()->setAuthToken(token);
        emit success(token);
        prepareGetUserType();
    } else {
        qDebug() << "Urmeaza eroare";
        QString errorMsg = doc["errors"][0]["message"].toString();
        emit loginFailed();
        qDebug() << spy.count();
    }
}

具有插槽的控制器类:

#ifndef LOGINCONTROLLER_H
#define LOGINCONTROLLER_H


#include <Utils/basecontroller.h>
#include <Utils/enginefactory.h>
#include <Utils/singleton.h>
#include <QQuickWindow>
#include <QQuickItem>
#include <QThread>
#include <QProperty>
#include <QQmlProperty>
#include "loginservice.h"
#include "draggableviewhelper.h"
#include <QMouseEvent>
class LoginController : public BaseController
{
    Q_OBJECT
private:
    QQuickWindow* window;
    QQuickItem* login;
    QQuickItem* userTextField;
    QQuickItem* passwordTextField;
    DraggableViewHelper* draggableViewHelper;
    QQuickItem* mouseArea;
    LoginService* service;
    QPointF lastMousePosition;
public:
    explicit LoginController(QObject *parent = nullptr);
    // BaseController interface

    void initialize();
   // void setService(BaseService* s);
    void setService(LoginService* s);
    void setLastMousePosition(QPointF lastMousePosition);

public slots:
    void handleLoginResponseSuccess(QString loginResponse);
    void handleLoginResponseFailed();
    void handlePositionChanged();
    void handleLogout();
};

#endif // LOGINCONTROLLER_H

初始化器方法

void LoginController::initialize()
{
    this->engine = Singleton<EngineFactory*>::GetInstance()->createEngine("qrc:/qml/LoginWindow.qml");
    this->window = qobject_cast<QQuickWindow*>(this->engine->rootObjects().first());
    // Create a draggable view helper, use window as input
    // Get the view from the engine
    this->draggableViewHelper = new DraggableViewHelper(this->window);
    this->window->setFlags(Qt::Window | Qt::FramelessWindowHint);
    this->login = window->findChild<QQuickItem*>("login");
    this->userTextField = QQmlProperty::read(this->login,"user").value<QQuickItem*>();
    this->passwordTextField = QQmlProperty::read(this->login,"password").value<QQuickItem*>();
    // Set the mouseArea with the mainMouseArea item of the window
    this->mouseArea = window->findChild<QQuickItem*>("mainMouseArea");
    // Connect onClicked from mouse area, to handleMove of this
    QObject::connect(this->mouseArea,SIGNAL(positionMoved()),this,SLOT(handlePositionChanged()));
}


void LoginController::setService(LoginService *s)
{
    this->service = s;//new LoginService;
    connect(this->service,SIGNAL(loginFailed()),this,SLOT(handleLoginResponseFailed()));
    connect(this->service,SIGNAL(success(QString)),this,SLOT(handleLoginResponseSuccess(QString)));
    connect(login,SIGNAL(doLogin(QString,QString)),this->service,SLOT(requestLogin(QString,QString)));
    this->dumpObjectInfo();
    this->service->dumpObjectInfo();
}

插槽

void LoginController::handleLoginResponseFailed()
{

    qDebug() << "Failed";
    QQmlProperty::write(this->userTextField,"state",QVariant::fromValue(QString{"default-error"}));
    QQmlProperty::write(this->passwordTextField,"state",QVariant::fromValue(QString{"password-error"}));
}

这是main.cpp文件,其中创建对象是

    QApplication app1(argc, argv);
    LoginController* loginCtrl = new LoginController;
    LoginService* loginService = new LoginService;
    QObject::connect(loginService, &LoginService::userTypeRecived,[&](){
        qDebug() << "Failed to login";
    });
    qDebug() << loginService;
    loginCtrl->initialize();
    loginCtrl->setService(loginService);
    //This will trigger the signal
    // loginService->loginResponse("{\"errors\":[{\"message\":\"Please enter valid credentials\",\"locations\":[{\"line\":1,\"column\":12}],\"path\":[\"tokenAuth\"]}],\"data\":{\"tokenAuth\":null}}");
    return app1.exec();

I've been having this problem for few weeks, still didn't found a solution anywhere. I did everything I could to find the problem, everything looks good but for some reason it doesn't work.
I tested the connection, between the loginFailed() signal, and handleLoginFailed() slot, it returned True, printed the object info, it shows the connections. Tried different Qt::connectionTypes, nothing works.

The two objects are defined bellow.

LoginService.h

#ifndef LOGINSERVICE_H
#define LOGINSERVICE_H

#include <QObject>
#include <QVariant>
#include "libs/qubeapi/QubeAPI.h"
#include "libs/qubeapi/LoginCommand.h"
#include "libs/qubeapi/APIBridge.h"
#include "libs/mge-users/User.h"
#include "libs/mge-users/permissionfactory.h"
#include "Utils/serverstate.h"
#include "Utils/singleton.h"
#include "Utils/baseservice.h"
class LoginService : public QObject
{
    Q_OBJECT
    QubeAPI* api;
    APIBridge* bridge;
    LoginCommand* loginCmd;
    QString m_userType;

    QString m_firstName;

    QString m_lastName;

    User *m_user;

public:
    explicit LoginService(QObject *parent = nullptr);
    Q_PROPERTY(QString userType READ userType WRITE setUserType NOTIFY userTypeChanged)
    Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY firstNameChanged)
    Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged)
    Q_PROPERTY(User* user READ user WRITE setUser NOTIFY userChanged)
    const QString &userType() const;
    void setUserType(const QString &newUserType);

    const QString &firstName() const;
    void setFirstName(const QString &newFirstName);

    const QString &lastName() const;
    void setLastName(const QString &newLastName);

    User *user() const;
    void setUser(User *newUser);


signals:
    void success(QString token);
    void loginFailed();
    void userTypeChanged();
    void firstNameChanged();
    void lastNameChanged();
    void staffLogout();
    void userTypeRecived();
    void userChanged();

public slots:
    void requestLogin(QString userName, QString password);
    void loginResponse(QString jsonData);
    void doClose();

    void prepareGetUserType();
    void loadUserType(QString jsonData);




};

#endif // LOGINCONTROLLER_H

The function that emits the signal:

void LoginService::loginResponse(QString jsonData)
{

    QSignalSpy spy(this,SIGNAL(loginFailed()));
    if(jsonData == "") {
        emit Singleton<ServerState>::GetInstance().offlineServer();
        return;
    }
    QJsonDocument doc = QJsonDocument::fromJson(jsonData.toUtf8());
    QString token = doc["data"]["tokenAuth"]["token"].toString();

    if(!token.isEmpty()) {
        UserSession::getInstance()->setAuthToken(token);
        emit success(token);
        prepareGetUserType();
    } else {
        qDebug() << "Urmeaza eroare";
        QString errorMsg = doc["errors"][0]["message"].toString();
        emit loginFailed();
        qDebug() << spy.count();
    }
}

The controller class that has the slot:

#ifndef LOGINCONTROLLER_H
#define LOGINCONTROLLER_H


#include <Utils/basecontroller.h>
#include <Utils/enginefactory.h>
#include <Utils/singleton.h>
#include <QQuickWindow>
#include <QQuickItem>
#include <QThread>
#include <QProperty>
#include <QQmlProperty>
#include "loginservice.h"
#include "draggableviewhelper.h"
#include <QMouseEvent>
class LoginController : public BaseController
{
    Q_OBJECT
private:
    QQuickWindow* window;
    QQuickItem* login;
    QQuickItem* userTextField;
    QQuickItem* passwordTextField;
    DraggableViewHelper* draggableViewHelper;
    QQuickItem* mouseArea;
    LoginService* service;
    QPointF lastMousePosition;
public:
    explicit LoginController(QObject *parent = nullptr);
    // BaseController interface

    void initialize();
   // void setService(BaseService* s);
    void setService(LoginService* s);
    void setLastMousePosition(QPointF lastMousePosition);

public slots:
    void handleLoginResponseSuccess(QString loginResponse);
    void handleLoginResponseFailed();
    void handlePositionChanged();
    void handleLogout();
};

#endif // LOGINCONTROLLER_H

The initializer methods

void LoginController::initialize()
{
    this->engine = Singleton<EngineFactory*>::GetInstance()->createEngine("qrc:/qml/LoginWindow.qml");
    this->window = qobject_cast<QQuickWindow*>(this->engine->rootObjects().first());
    // Create a draggable view helper, use window as input
    // Get the view from the engine
    this->draggableViewHelper = new DraggableViewHelper(this->window);
    this->window->setFlags(Qt::Window | Qt::FramelessWindowHint);
    this->login = window->findChild<QQuickItem*>("login");
    this->userTextField = QQmlProperty::read(this->login,"user").value<QQuickItem*>();
    this->passwordTextField = QQmlProperty::read(this->login,"password").value<QQuickItem*>();
    // Set the mouseArea with the mainMouseArea item of the window
    this->mouseArea = window->findChild<QQuickItem*>("mainMouseArea");
    // Connect onClicked from mouse area, to handleMove of this
    QObject::connect(this->mouseArea,SIGNAL(positionMoved()),this,SLOT(handlePositionChanged()));
}


void LoginController::setService(LoginService *s)
{
    this->service = s;//new LoginService;
    connect(this->service,SIGNAL(loginFailed()),this,SLOT(handleLoginResponseFailed()));
    connect(this->service,SIGNAL(success(QString)),this,SLOT(handleLoginResponseSuccess(QString)));
    connect(login,SIGNAL(doLogin(QString,QString)),this->service,SLOT(requestLogin(QString,QString)));
    this->dumpObjectInfo();
    this->service->dumpObjectInfo();
}

The slot

void LoginController::handleLoginResponseFailed()
{

    qDebug() << "Failed";
    QQmlProperty::write(this->userTextField,"state",QVariant::fromValue(QString{"default-error"}));
    QQmlProperty::write(this->passwordTextField,"state",QVariant::fromValue(QString{"password-error"}));
}

This is the main.cpp file, where the objects are created

    QApplication app1(argc, argv);
    LoginController* loginCtrl = new LoginController;
    LoginService* loginService = new LoginService;
    QObject::connect(loginService, &LoginService::userTypeRecived,[&](){
        qDebug() << "Failed to login";
    });
    qDebug() << loginService;
    loginCtrl->initialize();
    loginCtrl->setService(loginService);
    //This will trigger the signal
    // loginService->loginResponse("{\"errors\":[{\"message\":\"Please enter valid credentials\",\"locations\":[{\"line\":1,\"column\":12}],\"path\":[\"tokenAuth\"]}],\"data\":{\"tokenAuth\":null}}");
    return app1.exec();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文