当前位置:编程学习 > wap >>

qt 按钮快速连续点击过程中,第二次点击时响应问题


     多次快速点击同一个按钮时,如果第一次点击的响应尚未处理结束,在这个时间段内不再响应任何其它点击;我是通过一个静态全局变量判断是否要执行后续操作的,由于槽函数是按照点击顺序顺序执行的,所以在槽函数返回前发送一个信号到队列,对变量进行复位。
     问题是按照我的理解,第一次点击槽函数全部执行,接着是快速的第二次点击的响应(由于第一次点击的槽函数尚未执行结束,因此第二次的点击的槽函数应该不满足条件返回的),最后才是响应emit信号的。为什么第二次响应的是emit信号呢?
     我的代码如下:
int MainWindow::bStatus = 0;//static类型
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QPushButton* button1 = new QPushButton(this);
    button1->setGeometry(210,120,75,40);
    connect(button1,SIGNAL(clicked()),this,SLOT(info1()));
    connect(this,SIGNAL(flagGlobalBusy()),this,SLOT(set_GlobalBusy()),Qt::QueuedConnection);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::info1( )
{
    qDebug()<<"-----------BEGIN----------";
    qDebug()<<"bStatus: "<<bStatus;
    if( bStatus != 0 )
    {
        qDebug()<<"return because the button is busy! "<<bStatus;

        return;
    }
    bStatus++;
    qDebug()<<"bStatus++: "<<bStatus;

    QLineEdit* phoneEdit = new QLineEdit(this);
    QLabel* phoneLabel = new QLabel(phoneEdit);
    phoneEdit->setGeometry(180,80,75,30);
    phoneEdit->setAlignment( Qt::AlignCenter );
    QString str = "button_1";
    phoneEdit->setText(str);
    phoneLabel->setBuddy(phoneEdit);
    QThread::msleep(3000);
    emit flagGlobalBusy();
    phoneEdit->show();
    qDebug()<<"----------END----------- ";

}

void MainWindow::set_GlobalBusy()
{
    qDebug()<<"**********enter slots of flagGlobalBusy***********";

    bStatus = 0;
}

  快速点击4次时,执行结果如下:

-----------BEGIN---------- 
bStatus:  0 
bStatus++:  1 
----------END-----------  
**********enter slots of flagGlobalBusy*********** 
-----------BEGIN---------- 
bStatus:  0 
bStatus++:  1 
----------END-----------  
-----------BEGIN---------- 
bStatus:  1 
return because the button is busy!  1 
-----------BEGIN---------- 
bStatus:  1 
return because the button is busy!  1 
**********enter slots of flagGlobalBusy*********** 

为什么第二次响应的是emit信号,而不是第二次点击按钮时的点击信号?
--------------------编程问答-------------------- connect(button1,SIGNAL(clicked()),this,SLOT(info1()), Qt::QueuedConnection);
默认是自动连接的,加上队列连接看看行不行

--------------------编程问答-------------------- 信号与槽不是实时的,而且设置一个全局变量还用信号与槽有点滥用了。问题可能就出在这个地方。给你两个思路,一是直接在槽函数开始的时候操作flag,二是派生按钮类,重写它的press事件,第二种的可控性和实时性更强,只是有点麻烦。需求总要有代价 --------------------编程问答-------------------- 这段代码主要处理的是防止按钮重复点击问题,如果不用信号与槽来复位变量,而是在点击响应函数返回前将该变量复位的话,按钮仍然会重复响应,响应应该是按照信号队列里面信号的顺序依次响应的吧。本段代码就是没能防止第二次点击,其它次点击正常 --------------------编程问答--------------------
引用 3 楼 xnjd12 的回复:
而是在点击响应函数返回前将该变量复位的话,按钮仍然会重复响应,响应应该是按照信号队列里面信号的顺序依次响应的吧。

在函数刚开始的时候置flag,结束的时候复位flag不是很自然的思想么? --------------------编程问答-------------------- 如果那个槽没有异步调用其他操作,是不可能出现重复执行的,因为控制权还没有返回事件循环。那个busy信号,当status=0时,会触发一次,其实是当作事件来放到事件队列里的,而你点按钮又会产生事件,所以执行的顺序和事件被放入队列的顺序有关。 --------------------编程问答-------------------- 可不可以试着点击之后设置按钮setEnable(false),处理完后setEnable(true). --------------------编程问答--------------------
引用 4 楼 HeadmasterWang 的回复:
Quote: 引用 3 楼 xnjd12 的回复:

而是在点击响应函数返回前将该变量复位的话,按钮仍然会重复响应,响应应该是按照信号队列里面信号的顺序依次响应的吧。

在函数刚开始的时候置flag,结束的时候复位flag不是很自然的思想么?


4楼这么说,意思是,你不需要这个“connect(this,SIGNAL(flagGlobalBusy()),this,SLOT(set_GlobalBusy()),Qt::QueuedConnection);”,因为槽set_GlobalBusy中的内容直接放到槽info1中的对应位置就可以了,不需要还弄一个connect。而且问题很可能就是因为你这里用了槽去重置你的全局变量的状态。可能你是认为第二个连接你用了QueuedConnection,所以不应该出现你看到的结果,但是谁知道操作系统在后面做了什么事情呢。

6楼的思路也是可以的。

都可以解决你要解决的问题。都是在第一次点击的后续处理没有完成时,直接忽略第二次甚至第N次的点击。其实你自己的思路也是这样的…… --------------------编程问答--------------------
引用 5 楼 Kenier 的回复:
如果那个槽没有异步调用其他操作,是不可能出现重复执行的,因为控制权还没有返回事件循环。那个busy信号,当status=0时,会触发一次,其实是当作事件来放到事件队列里的,而你点按钮又会产生事件,所以执行的顺序和事件被放入队列的顺序有关。


也就是说,可能楼主认为第二次按钮点击的事件处理应该在全局状态变量被重置之前,因为第二个connect你用了QueuedConnection嘛,所以你应该多做一下这个实验,验证是不是事件队列里真是这个顺序。至少这里给人的感觉是系统把重置事件放到了第二次按钮点击之前处理了。
补充:移动开发 ,  Qt
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,