Qt-如何在不兼容的信号和插槽之间使用连接

发布于 2024-11-04 02:31:25 字数 213 浏览 1 评论 0原文

我正在尝试做一个游戏。在此我想调用一个函数,该函数将收到一个 point 。但这个函数应该由定时器的超时信号调用。谁能说一下如何实现这一目标。以下是所需/错误代码

Point p(a,b);

connect(timer,SIGNAL(timedout()),this,startDestruction(p));

有人能说一下如何实现这一点吗?

I am trying to do a game. In this I want to call a function, that function will receive a point . But this function should be invoked by a timer's timedout signal. Can anybody say how to achieve this. Below is the required/error code

Point p(a,b);

connect(timer,SIGNAL(timedout()),this,startDestruction(p));

Can anybody say how to achieve this?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

巨坚强 2024-11-11 02:31:25

你的设计有缺陷;

  • 您在堆栈上创建 p
  • 您希望 Qt 防止该对象死亡并在调用信号时重用它

Your design is flawed;

  • you create p on stack
  • you want Qt to prevent this object from dying and reuse it whenever a signal is called
明媚如初 2024-11-11 02:31:25

您的问题通常可以通过使用 QSignalMapper 来解决,但这仅是支持QStringintQWidget*QObject*作为参数类型。

如果您想使用其他类型,您需要实现自己的信号映射器(您不讨厌 Qt 不允许您创建从 QObject 派生的类模板吗?:),如下所示

class PointSignalMapper : public QObject {
    Q_OBJECT
public:
    explicit PointSignalMapper( QObject * parent=0 )
        : QObject( parent ), m_map() {}

    void setMapping( QObject * sender, const Point & p ) {
        if ( sender )
            m_map[sender] = p;
    }

public Q_SLOTS:
    void map() {
        map( sender() );
    }
    void map( QObject * sender ) {
        if ( !sender )
            return;
        const QMap<QObject*,Point>::const_iterator
            it = m_map.constFind( sender );
        if ( it != m_map.constEnd() )
            emit mapped( it.value() );
    }
Q_SIGNALS:
    void mapped( const Point & p );

private:
    QMap<QObject*,Point> m_map;
};

: :

PointSignalMapper * mapper = new PointSignalMapper( this );
connect( mapper, SIGNAL(mapped(Point)), this, SLOT(pointDestroyed(Point)) );

mapper->setMapping( qObject1, point1 );
connect( qObject1, SIGNAL(timedout()), mapper, SLOT(map()) );

mapper->setMapping( qObject2, point2 );
connect( qObject2, SIGNAL(timedout()), mapper, SLOT(map()) );

// ...

根据您的具体情况:

Point p(a,b);
PointSignalMapper * mapper = new PointSignalMapper( this ); // added
mapper->setMapping( timer, p );                             // added
connect( timer, SIGNAL(timedout()), mapper, SLOT(map()) );  // added
connect( mapper, SIGNAL(mapped(Point)),                     // modified
         this, startDestruction(Point)) )

Your problem is usually solved by using QSignalMapper, but that only supports QString, int, QWidget*, and QObject* as parameter types.

If you want to use other types, you need to implement your own signal mapper (don't you hate how Qt doesn't let you make class templates derived from QObjects? :) like this:

class PointSignalMapper : public QObject {
    Q_OBJECT
public:
    explicit PointSignalMapper( QObject * parent=0 )
        : QObject( parent ), m_map() {}

    void setMapping( QObject * sender, const Point & p ) {
        if ( sender )
            m_map[sender] = p;
    }

public Q_SLOTS:
    void map() {
        map( sender() );
    }
    void map( QObject * sender ) {
        if ( !sender )
            return;
        const QMap<QObject*,Point>::const_iterator
            it = m_map.constFind( sender );
        if ( it != m_map.constEnd() )
            emit mapped( it.value() );
    }
Q_SIGNALS:
    void mapped( const Point & p );

private:
    QMap<QObject*,Point> m_map;
};

Usage:

PointSignalMapper * mapper = new PointSignalMapper( this );
connect( mapper, SIGNAL(mapped(Point)), this, SLOT(pointDestroyed(Point)) );

mapper->setMapping( qObject1, point1 );
connect( qObject1, SIGNAL(timedout()), mapper, SLOT(map()) );

mapper->setMapping( qObject2, point2 );
connect( qObject2, SIGNAL(timedout()), mapper, SLOT(map()) );

// ...

In your specific case:

Point p(a,b);
PointSignalMapper * mapper = new PointSignalMapper( this ); // added
mapper->setMapping( timer, p );                             // added
connect( timer, SIGNAL(timedout()), mapper, SLOT(map()) );  // added
connect( mapper, SIGNAL(mapped(Point)),                     // modified
         this, startDestruction(Point)) )
别低头,皇冠会掉 2024-11-11 02:31:25

创建一个用作中间槽的方法,如下所示。

Point p(a,b);
connect(timer, SIGNAL(timedout()), this, q);

q() {
    startDestruction(this->p)
}

Create a method to use as an intermediate slot, like this.

Point p(a,b);
connect(timer, SIGNAL(timedout()), this, q);

q() {
    startDestruction(this->p)
}
雾里花 2024-11-11 02:31:25

您通常必须创建一个由计时器触发的中间槽,然后使用该点调用 startDestruction。

You usually have to create an intermediate slot that is triggered by the timer and then calls startDestruction with the point.

演多会厌 2024-11-11 02:31:25

重新设计你的类怎么样,让 startDestruction() 成为 p 的一个槽。当 p.startDestruction() 被调用时,它会发出一个信号来通知主类。

connect(timer,SIGNAL(timedout()),p,startDestruction());
connect(p,SIGNAL(destroyed()),this,destroyHandle());

How about redesign your class, so that startDestruction() is a slot of p. While p.startDestruction() is call, it'll emit a signal to notify the main class.

connect(timer,SIGNAL(timedout()),p,startDestruction());
connect(p,SIGNAL(destroyed()),this,destroyHandle());
丘比特射中我 2024-11-11 02:31:25

这是一个有效的、不那么简单的例子。

Qt 要求模拟的 QObject 派生类不在主文件中,这就是 Pipe 被分开的原因。使用对象作为包装器而不是函数可以提供更大的灵活性,并且不需要将变量封装在字段中(无需更改架构)。

输出

Destroyed target at [40, 12]
Destroyed target at [41, 11]
Destroyed target at [42, 10]

ma​​in.cpp

#include "Game.h"
#include "Pipe.h"

#include <QtCore/QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    Game game;
    Point target(40, 12);
    Pipe pipe(&game, &target);

    pipe.pass();
    QTimer::singleShot(500, &pipe, SLOT(pass()));
    QTimer::singleShot(1000, &pipe, SLOT(pass()));
    QTimer::singleShot(2000, &app, SLOT(quit()));

    return app.exec();
}

Game.h

#ifndef GAME_H
#define GAME_H

#include <iostream>

struct Point {
    int x;
    int y;

    Point(int _x, int _y) : x(_x), y(_y) {}
};

class GameInterface {
public:
    virtual void startDesturction(Point * pt) = 0;
};

class Game : public GameInterface {
public:
    virtual void startDesturction(Point * pt)  {
        std::cout<<"Destroyed target at ["<<pt->x<<", "
                 <<pt->y<<"]"<<std::endl;

        //shift
        pt->x += 1;
        pt->y -= 1;
    }
};

#endif // GAME_H

Pipe.h

#ifndef PIPE_H
#define PIPE_H

#include "Game.h"

#include <QObject>

class Pipe : public QObject {
    Q_OBJECT

public:
    Pipe(GameInterface * game, Point * target)
        : QObject(), m_game(game), m_target(target) {}
    virtual ~Pipe() {}

public slots:
    void pass() {
        m_game->startDesturction(m_target);
    }

private:
    GameInterface * m_game;
    Point * m_target;
};

#endif // PIPE_H

Here's working, not-so-minimal example.

Qt requires that the mocked QObject-derived class is not in the main file, and that's why Pipe is separated. Using object as the wrapper instead of a function gives greater flexibility and does not require you to encapsulate variable in a field (no architecture changes).

Output

Destroyed target at [40, 12]
Destroyed target at [41, 11]
Destroyed target at [42, 10]

main.cpp

#include "Game.h"
#include "Pipe.h"

#include <QtCore/QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    Game game;
    Point target(40, 12);
    Pipe pipe(&game, &target);

    pipe.pass();
    QTimer::singleShot(500, &pipe, SLOT(pass()));
    QTimer::singleShot(1000, &pipe, SLOT(pass()));
    QTimer::singleShot(2000, &app, SLOT(quit()));

    return app.exec();
}

Game.h

#ifndef GAME_H
#define GAME_H

#include <iostream>

struct Point {
    int x;
    int y;

    Point(int _x, int _y) : x(_x), y(_y) {}
};

class GameInterface {
public:
    virtual void startDesturction(Point * pt) = 0;
};

class Game : public GameInterface {
public:
    virtual void startDesturction(Point * pt)  {
        std::cout<<"Destroyed target at ["<<pt->x<<", "
                 <<pt->y<<"]"<<std::endl;

        //shift
        pt->x += 1;
        pt->y -= 1;
    }
};

#endif // GAME_H

Pipe.h

#ifndef PIPE_H
#define PIPE_H

#include "Game.h"

#include <QObject>

class Pipe : public QObject {
    Q_OBJECT

public:
    Pipe(GameInterface * game, Point * target)
        : QObject(), m_game(game), m_target(target) {}
    virtual ~Pipe() {}

public slots:
    void pass() {
        m_game->startDesturction(m_target);
    }

private:
    GameInterface * m_game;
    Point * m_target;
};

#endif // PIPE_H
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文