QPushButton槽函数触发两次的问题(转)

以前经常使用qt creator界面管理直接跳转到槽函数没发现这个问题,今天手动写了个槽函数发现按键会触发两次。根据网上的说法是按键会自动连接一个槽函数,如果我们手动添加的槽函数命名规则符合槽函数的命名规则的话,此时就会出现触发两次的问题。

  带着这个疑问,我们去代码里找答案。首先是在界面自动生成的ui_mainwindow.h(由你按键所在的界面决定),我们找到了自动建立槽函数连接的代码

1

2

retranslateUi(MainWindow);

QMetaObject::connectSlotsByName(MainWindow);

  继续跟踪发现这个系统函数connectSlotsByName是定义在qobject中,切换过去发现文件头有如下声明

1

2

3

4

5

6

7

\section1 Auto-Connection

Qt's meta-object system provides a mechanism to automatically connect

signals and slots between QObject subclasses and their children. As long

as objects are defined with suitable object names, and slots follow a

simple naming convention, this connection can be performed at run-time

by the QMetaObject::connectSlotsByName() function.

  大意就是我们之前说的如果槽函数的命名满足一定形式的简单规则,那么这个函数就会将信号和槽自动连接起来,跟踪源代码我们看下规则到底是怎样的

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

void QMetaObject::connectSlotsByName(QObject *o){   if (!o)

        return;

    const QMetaObject *mo = o->metaObject();

    Q_ASSERT(mo);

    const QObjectList list = qFindChildren<QObject *>(o, QString());

    for (int i = 0; i < mo->methodCount(); ++i) {

        const char *slot = mo->method(i).signature();

        Q_ASSERT(slot);

        if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')

            continue;

        bool foundIt = false;

        for(int j = 0; j < list.count(); ++j) {

            const QObject *co = list.at(j);

            QByteArray objName = co->objectName().toAscii();

            int len = objName.length();

            if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')

                continue;

            int sigIndex = co->d_func()->signalIndex(slot + len + 4);

            if (sigIndex < 0) { // search for compatible signals

                const QMetaObject *smo = co->metaObject();

                int slotlen = qstrlen(slot + len + 4) - 1;

                for (int k = 0; k < co->metaObject()->methodCount(); ++k) {

                    QMetaMethod method = smo->method(k);

                    if (method.methodType() != QMetaMethod::Signal)

                        continue;

                    if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {

                        int signalOffset, methodOffset;

                        computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);

                        sigIndex = k + - methodOffset + signalOffset;

                        break;

                    }

                }

            }

            if (sigIndex < 0)

                continue;

            if (QMetaObjectPrivate::connect(co, sigIndex, o, i)) {

                foundIt = true;

                break;

            }

        }

        if (foundIt) {

            // we found our slot, now skip all overloads

            while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)

                  ++i;

        else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {

            qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);

        }

    }

}

大概看了下(有兴趣的可自行研究),要满足如图上红色标志处的如下两个规则1、首先是要以on_开头2、其次,要以“_”+行为结束,例如_clicked了解这个后我们再回到之前的问题,假如一个按键QPushButton,如果我们定义一个槽函数on_QPushButton_clicked(void)的话,此时不需要额外进行connect()操作,程序编译时会自动将槽函数连接起来。而这次如果我们额外进行connect操作的话,就会出现槽函数触发两次的情况了。解决的办法很简单,手动连接时槽函数名字规避命名规则就行了,如上我们定义成QPushButton_clicked(void),或者在connect时使用qt::uniqueconnection进行强制制定。

转自:https://www.cnblogs.com/zwj412/p/10176260.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值