• 11590阅读
  • 52回复

[提问]如何让两个button的槽函数一个先执行,一个后执行呢? [复制链接]

上一主题 下一主题
离线foxgod
 

只看楼主 倒序阅读 楼主  发表于: 2013-10-24
我现在有两个button,每个button都有一个槽函数,第一个button的槽函数的执行需要一些时间,我想做的是,第一个button还没有执行完的时候,我点击第二个button,就不执行第二个button里面的槽函数,我不想使用变量才判断,可以使用event来实现吗?我使用QCoreApplication::postEvent().貌似没有作用。


代码如何::
代码 code.rar (3 K) 下载次数:10








离线rpdhunter

只看该作者 1楼 发表于: 2013-10-24
在一个槽函数里面调用另一个槽函数就可以了
离线friendbaby

只看该作者 2楼 发表于: 2013-10-24
如果两个槽在同一个线程,不需要做任何修改,因为执行是有先后顺序的。
如果不在同一个线程,在执行第二个槽函数的时候先要判断第一个槽函数有没有完成,不一定非要添加一个bool量,跟你的函数功能有关系。
Smiling is best language , can express everything , also can conceal everything.
离线jdwx

只看该作者 3楼 发表于: 2013-10-24
回 楼主(foxgod) 的帖子
点第一个button,槽里先禁用第二个button(setEnabled(false)),这样第二个button变灰无法点击,槽里最后启用第二个button,Ok。
发帖时要说明:操作系统、Qt版本、编译器,这样能更快的得到回复。
离线foxgod

只看该作者 4楼 发表于: 2013-10-25
回 3楼(jdwx) 的帖子
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()),Qt::DirectConnection);

connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::DirectConnection);

我在连接信号和槽的时候使用了Qt::DirectConnection,这样点击多个button,他们应该就是同步连接他们的槽函数了吧,没有先后顺序吧,不会信号在消息队列里面,等待上一个槽函数执行完才执行下一个是不???我这里使用了QSignalMapper来管理多个button。可是我点击多个button的时候
无法阻止其他button不相应。楼上的是个办法,但是我最终是想解决别的问题,button只是个简单的例子,我就是想点击多个button的时候,阻止其他button执行他们的槽函数。
离线foxgod

只看该作者 5楼 发表于: 2013-10-25
回 2楼(friendbaby) 的帖子
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()),Qt::DirectConnection);

connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::DirectConnection);

我在连接信号和槽的时候使用了Qt::DirectConnection,这样点击多个button,他们应该就是同步连接他们的槽函数了吧,没有先后顺序吧,不会信号在消息队列里面,等待上一个槽函数执行完才执行下一个是不???我这里使用了QSignalMapper来管理多个button。可是我点击多个button的时候
无法阻止其他button不相应。楼上的是个办法,但是我最终是想解决别的问题,button只是个简单的例子,我就是想点击多个button的时候,阻止其他button执行他们的槽函数。
离线dbzhang800

只看该作者 6楼 发表于: 2013-10-25
你能不能先说一下你想解决什么问题。另外:“我就是想点击多个button的时候,阻止其他button执行他们的槽函数。”  具体是要表达什么意思,如何阻止?

离线justwake

只看该作者 7楼 发表于: 2013-10-25
第一个槽函数里面绑定第二个button的connect
离线foxgod

只看该作者 8楼 发表于: 2013-10-28
回 6楼(dbzhang800) 的帖子
connect(button, SIGNAL(), signalMapper, SLOT(2),Qt::DirectConnection);

connect(signalMapper,SIGNAL(),this,SLOT(1),Qt::DirectConnection);

我用signalMap管理多个button,在1这个槽函数里面我管理哪个button做了什么,我现在因为连续快速点击多个button的时候,会造成我程序崩溃,所以我想这样做,点击一个button后,在连续点击其他的button,如果点击的第一个button还在执行中,点击其他button的响应不执行。

或者是我点击一个button去执行一个槽函数,但是我如果我连续点击这个button,貌似槽函数也连续执行了很多次,如果可以控制连续点击一个button,只让他的槽函数执行一次。


离线foxgod

只看该作者 9楼 发表于: 2013-10-28
回 7楼(justwake) 的帖子
我用signalMapper来管理多个button
离线dbzhang800

只看该作者 10楼 发表于: 2013-10-28
用了siignalMapper,也就是你关心的这些button调用的是同一个槽,对吧?

根据你描述的现象,你的槽内:要么是启用了其他的线程等异步的api,要么是嵌套了事件循环(通过那些exec()函数,或者QCoreApplication::processEvents() 等)

无论是那种情况,设置一个flag标记似乎都不应该是难事
离线rpdhunter

只看该作者 11楼 发表于: 2013-10-28
回 8楼(foxgod) 的帖子
很简单啊,楼主的问题是槽函数运行可能需要一定时间,在这个时间内再触发槽函数会造成程序崩溃。
那么,可以采用如下的方法:
1.在执行某个button槽函数之前,将需要管理的多个button(包括自己的)的所有槽函数解除连接(disconnect)
2.槽函数执行完毕,将需要管理的多个button(包括自己的)的所有槽函数恢复连接(connect)
操作起来很容易,只需要建立2个函数,一个解绑f1(),一个建立绑定f2(),在所有的槽函数开头插入f1(),结尾插入f2
离线foxgod

只看该作者 12楼 发表于: 2013-10-28
你说的实验了不行,首先,我用signalMap管理多个button,所有button都通过signalmap的同一个槽函数管理。你这样在进入槽函数后先disconnect,然后再case 执行后才connect,还是没有阻止其他button,不写connect,则可以。
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()),Qt::DirectConnection);将每个button和signalmap链接。
signalMapper->setMapping(button, (QObject*)button);
connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::DirectConnection);点击不同button用siganlmap处理。
槽函数
  1. void Widget::slot(QObject *obj)
  2. {
  3.     disconnect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)));
  4.     switch(obj->objectName().toInt())
  5.     {
  6.     case 0:
  7.         qDebug()<<"222";
  8.         break;
  9.     case 1:  
  10.         qDebug()<<"333";
  11.         break;
  12.     case 2:
  13.         qDebug()<<"444";
  14.         break;
  15.     }
  16. 你说的实验了不行,首先,我用signalMap管理多个button,所有button都通过signalmap的同一个槽函数管理。你这样在进入槽函数后先disconnect,然后再case 执行后才connect,还是没有阻止其他button,不写connect,则可以。
  17. connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()),Qt::DirectConnection);将每个button和signalmap链接。
  18. signalMapper->setMapping(button, (QObject*)button);
  19. connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::DirectConnection);点击不同button用siganlmap处理。
  20. 槽函数
  21. void Widget::slot(QObject *obj)
  22. {
  23.     disconnect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)));
  24.     switch(obj->objectName().toInt())
  25.     {
  26.     case 0:
  27.         qDebug()<<"222";
  28.         break;
  29.     case 1:  
  30.         qDebug()<<"333";
  31.         break;
  32.     case 2:
  33.         qDebug()<<"444";
  34.         break;
  35.     }
  36.     //connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::DirectConnection);
  37. }
  38. }
  39. 按照上面的写法则可以阻止其他button相应,但是有一个问题,没有恢复原来的状态,我的意思是在点击不同的button顺序就不可以实现屏蔽别的button了。
  40. 如果把注释取消,那么久不能阻止其他button的相应了,就是每个button都执行了。



离线foxgod

只看该作者 13楼 发表于: 2013-10-28
回 10楼(dbzhang800) 的帖子
设置一个flag是可以,但是只对第一次点击多个button起作用,第二次点击点击多个button就不起作用了。还有你说的这个postEvent(),我在程序里面没写,曾试验者写过,但是没成功,不知道怎么用。就是我想想做成点击多个button,只有第一个被点击的button,起作用,其他的button都不去执行他们的槽函数。等一个button执行完后,恢复以前的状态,在连续多次点击不同button(假设这次第二个button先点击),这样就是第二个button相应,其他button不相应。


  1. void Widget::slot(QObject *obj)
  2. {
  3.     disconnect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)));
  4.     switch(obj->objectName().toInt())
  5.     {
  6.     case 0:
  7.         qDebug()<<"222";
  8.         break;
  9.     case 1:  
  10.         qDebug()<<"333";
  11.         break;
  12.     case 2:
  13.         qDebug()<<"444";
  14.         break;
  15.     }
离线dbzhang800

只看该作者 14楼 发表于: 2013-10-28
你给的代码不可能出现你描述的问题。不需要任何玩外操作,也是一个执行完按钮动作,再执行的另外一个。不会出现当前槽执行期间响应其他按钮的问题。

要么你贴的代码和你用的不一致。要么你感到疑惑的这个问题其实本就不存在。
离线foxgod

只看该作者 15楼 发表于: 2013-10-28
回 14楼(dbzhang800) 的帖子
我刚才贴的代码,确实是只执行了button1,其他两个button没有执行,但是我的程序需要这样做,连续快速点击对个button,只有第一个button执行,其他button不执行,当第一个button执行完后,恢复初始状态


如果再次连续点击多个button,如果这个第二个button先被点击,则第二个button执行,其他button不执行,
但是现在我贴上去的代码,只有第一个点击多个button正常,第二个点击多个就不起作用了
离线dbzhang800

只看该作者 16楼 发表于: 2013-10-28
Re:回 14楼(dbzhang800) 的帖子
引用第15楼foxgod于2013-10-28 16:05发表的 回 14楼(dbzhang800) 的帖子 :
连续快速点击对个button,只有第一个button执行,其他button不执行,当第一个button执行完后,恢复初始状态
如果再次连续点击多个button,如果这个第二个button先被点击,则第二个button执行,其他button不执行,
.......

这是Qt的默认行为,不需要任何特殊操作。除非你发现Qt的一个bug(如果你可以通过一个小例子来重现问题,即可去提交Bug)。

至于你遇到的问题,你不妨好好调试你的程序,看看问题出在什么地方。
离线foxgod

只看该作者 17楼 发表于: 2013-10-28
回 16楼(dbzhang800) 的帖子
我想问版主,QT的默认行为就是点击一个button然后进入消息队列,等待第一个不button的槽函数执行完,然后执行第二个button的槽函数,难道我不可以在第一个button的槽函数执行完,阻止第二个button的槽函数执行。MFC都可以,我相信QT也可以
离线dbzhang800

只看该作者 18楼 发表于: 2013-10-28
第一个button的槽函数执行完之前,你不可能再次点中本button点中其他button。你应该了解,在执行耗时操作时,界面是死掉的。同样,执行不耗时的操作时,界面也是死掉的,只是时间短,我们感觉不到而已。
离线foxgod

只看该作者 19楼 发表于: 2013-10-28
我在QT帮助时,在connect中的第五个参数,如果是Qt::DirectConnection,那么他是直连,对这个参数,我理解是点击一个不button就去执行槽函数,不存在等待时间(不知道我理解的对不),你说的点击完一个button后,不能再次点击别的button,为什么不能点击,我这里测试就是不停的连续的点击我多个button,导致了崩溃。




离线dbzhang800

只看该作者 20楼 发表于: 2013-10-28
引用第19楼foxgod于2013-10-28 17:06发表的  :
我在QT帮助时,在connect中的第五个参数,如果是Qt::DirectConnection,那么他是直连,对这个参数,我理解是点击一个不button就去执行槽函数,不存在等待时间(不知道我理解的对不),



引用第19楼foxgod于2013-10-28 17:06发表的  :
你说的点击完一个button后,不能再次点击别的button,为什么不能点击,

我上一个帖子说的就是这个问题的答案。你写个简单的小程序应该就能测试。
引用第19楼foxgod于2013-10-28 17:06发表的  :
我这里测试就是不停的连续的点击我多个button,导致了崩溃。

所以你需要调试你的程序,而不是纠结于假象的问题。
离线foxgod

只看该作者 21楼 发表于: 2013-10-28
Qt::DirectConnection这种方式连接的话,是不是也是在消息队列里面,按照先进先出的顺序执行槽函数。
离线foxgod

只看该作者 22楼 发表于: 2013-10-28
回 20楼(dbzhang800) 的帖子
你知道如何获取消息队列里面的东西吗
离线dbzhang800

只看该作者 23楼 发表于: 2013-10-29
引用第21楼foxgod于2013-10-28 17:51发表的  :
Qt::DirectConnection这种方式连接的话,是不是也是在消息队列里面,按照先进先出的顺序执行槽函数。

这种情况下,不涉及Qt的事件队列。但既然你用过MFC,对系统底层应该比我清楚,键鼠事件等都会进入系统的消息队列。Qt作为一个库,处理的也只是系统派发的消息,至于这中间,Qt会不会有bug,需要你来验证。
离线friendbaby

只看该作者 24楼 发表于: 2013-10-30
单线程,是不会同时执行两个函数的。
Smiling is best language , can express everything , also can conceal everything.
离线friendbaby

只看该作者 25楼 发表于: 2013-10-30
Qt::DirectConnection 会直接跳到槽函数去执行,楼主可以调试一下。
你在第一个槽函数里面写一个死循环,界面会死掉。根本无法点击第二个按钮。
Smiling is best language , can express everything , also can conceal everything.
离线friendbaby

只看该作者 26楼 发表于: 2013-10-30
这里不存在消息队列,因为这不是多线程
Smiling is best language , can express everything , also can conceal everything.
离线foxgod

只看该作者 27楼 发表于: 2013-10-31
回 26楼(friendbaby) 的帖子
那就是我不能屏蔽第二个不button的信号了吗,我想问下,我们的事件在一个队列里面,一个个执行,那么我们的信号在那里放着呢,是和事件在一个队列里面放的吗,如果在一个队列里面放着,我如何执行完第一个,就不执行后面的呢
离线dbzhang800

只看该作者 28楼 发表于: 2013-11-01
不妨用几十行代码写个完整的可编译运行的,可以体现出你的问题所在的例子。然后发出来

不然,估计大家都不明白你到底是在哪儿遇到了问题,遇到了什么问题。
离线foxgod

只看该作者 29楼 发表于: 2013-11-01
  1. Widget::Widget(QWidget *parent) :
  2.     QWidget(parent),
  3.     ui(new Ui::Widget)
  4. {
  5.     ui->setupUi(this);  
  6.     signalMapper = new QSignalMapper(this);
  7.     for (int i = 0; i < 3; i++)
  8.     {
  9.         QPushButton *button = new QPushButton(this);
  10.         button->setObjectName(QString::number(i));
  11.         connect(button, SIGNAL(pressed()), signalMapper, SLOT(map()),Qt::QueuedConnection);//原始信号传递给signalmapper
  12.         signalMapper->setMapping(button, (QObject*)button);
  13.     }
  14.     connect(signalMapper,SIGNAL(mapped(QObject*)),this,SLOT(setBackground(QObject*)),Qt::QueuedConnection);
  15. }
  16. 这里我将多个button用signalMapper来管理。
  17. void Widget::setBackground(QObject *obj)
  18. {
  19.     qDebug()<<"setBackground";
  20.     myobject mobj;
  21.     switch(obj->objectName())
  22.     {
  23.     case 0:
  24.         qDebug()<<"enter button0";
  25.         break;
  26.     case 1:
  27.         qDebug()<<"enter button1";
  28.        break;
  29.     case 2:
  30.        qDebug()<<"enter button2";
  31.        break;
  32.     }
  33. }
我现在的情况是连续多次点击button1,那么现在点击的信号在队列里面一个个的执行。(假设现在点击了五次,那么就要执行五次),可是我只想执行一次(也就是在button1执行完后,在消息队列里面的其他信号要执行的槽函数我不想执行了),我如果设置一个bool变量来判断的话,让他第一次点击执行完变为true,这样可以阻止其他4次的点击,可是我什么时候恢复这个变量呢,如果第一次button执行完就恢复,那么其他4次还是执行了,没有起到作用,如果不恢复这个bool变量,那么在次点击这个button1,永远都不起作用了。我的效果是连续点击button1,假设点了5次,我只想执行一次,其他4次不执行,然后再等一秒,我再次连续5次点击button1,还是可以只执行一次,其他4次不执行。



第二种情况,如果我点击了button1,button2,button3,那么我想让button1执行,其他button不执行。或是点击顺序为button2,button1,button3那么我想让button2执行,其他button不执行。,可是这也遇到了一个情况,你设置一个bool变量可以阻止其他button执行,可是什么时候恢复这个bool变量呢,如果你在一个button执行完的时候恢复这个变量,相当于没有阻止其他button执行,求指教。我的效果是点击button1,button2,button3,我只想执行button1一次,其他button不执行,然后再等一秒,我再次点击button2,button3,button1,这次我只想button2执行,其他的不执行,也就是每次只执行首先点击的button,其他button不执行。


现在的问题是如何阻止其他button执行的问题,第二个是如何恢复的问题。
求指教


离线dbzhang800

只看该作者 30楼 发表于: 2013-11-01
你把 Qt::QueuedConnection 去掉,你说的这些问题不就都没了么?
离线foxgod

只看该作者 31楼 发表于: 2013-11-01
回 30楼(dbzhang800) 的帖子
问题依旧存在,你可以试验下。
我最开始就是什么都不写。也曾经实验过Qt::DirectConnection,都不可以。
离线foxgod

只看该作者 32楼 发表于: 2013-11-01
回 26楼(friendbaby) 的帖子
看看我的答案吧,
离线dbzhang800

只看该作者 33楼 发表于: 2013-11-01
还是我前面说的,不妨用几十行代码写个完整的 可编译运行的可以体现出你的问题所在的例子。然后发出来

不然,估计大家都不明白你到底是在哪儿遇到了问题,遇到了什么问题。
离线foxgod

只看该作者 34楼 发表于: 2013-11-01
回 33楼(dbzhang800) 的帖子
大哥你QQ多少,我觉得我的例子和我说的都很明显了呀
我的例子也就是写log,没啥,只要你能把我上面写的signalmap的槽函数里面,可以按照我说的阻止完后,在恢复就可以了,我没有别的要求。


离线dbzhang800

只看该作者 35楼 发表于: 2013-11-01
Re:回 33楼(dbzhang800) 的帖子
引用第34楼foxgod于2013-11-01 16:03发表的 回 33楼(dbzhang800) 的帖子 :
大哥你QQ多少,我觉得我的例子和我说的都很明显了呀
我的例子也就是写log,没啥,只要你能把我上面写的signalmap的槽函数里面,可以按照我说的阻止完后,在恢复就可以了,我没有别的要求。


所以才要你给出完整的例子嘛。因为你觉得你说明白了,但是其他人都还是一头雾水。

只需要一个几十行的例子就行了,一个 main.cpp 足够,连 .pro 文件都不需要。保证其他人只要
qmake -project
qmake
make
就可运行即可。

---

离线foxgod

只看该作者 36楼 发表于: 2013-11-01
回 35楼(dbzhang800) 的帖子
代码我已经上传了。点击下面的button,上面的button是我在界面上拖出来的。
离线dbzhang800

只看该作者 37楼 发表于: 2013-11-01
恩,代码看到了。建议你好好理理自己的思路,你的目的是什么。

程序执行是受你的代码控制的,但是你的代码可能并不是你想表达的。

-----

不妨假象自己不懂程序,只是个用户。从用户的角度来描述,你想要程序做什么。(不要提信号、槽、等等概念)。

比如说,点击按钮1之后,其后10s内,忽略任何键盘和鼠标操作(除非点击xxx,或10s时间到)。等等
离线dbzhang800

只看该作者 38楼 发表于: 2013-11-01
可能是想要的只是一个很简单的东西,可是你自己把它们想复杂了。
离线foxgod

只看该作者 39楼 发表于: 2013-11-01
回 37楼(dbzhang800) 的帖子
我现在的情况是什么呢,就是连续点击button,消息堆积在队列里面,不知道什么原因造成了崩溃,当然可能不是信号和槽的问题,但是我就是不想消息推挤,就是想在队列里面有5个消息,我就执行一个消息。后面其他的都不执行,也就是我button1点击后,后面所有的都不执行,比如鼠标事件,移动事件,button2 ,button3触发事件,我都要屏蔽,不执行了。我想我这次说明白了吧,我的代码就是看看怎么样可以屏蔽。

快速回复
限100 字节
 
上一个 下一个