سؤال

I'm using a QTimer to smoothly change the size of a label: it should slowly grow when I hover the mouse over a button, and slowly collapse (decrease it's size until it dissapears) when the mouse leaves the button.

I have two timers in my form's class:

QTimer oTimer, cTimer;//oTimer for expanding, cTimer for collapsing

In my form's constructor, I'm setting the timer's values and connecting the button's mouseOver and mouseOut signals to my form's slots:

oTimer.setInterval( 25 );
cTimer.setInterval( 25 );

connect( ui.Button, 
         SIGNAL(mouseEntered(QString)), 
         this, 
         SLOT(expandHorizontally(QString)) );
connect( ui.Button, 
         SIGNAL(mouseLeft(QString)), 
         this, 
         SLOT(compactHorizontally(QString)) );

Now, in these slots I connect the corresponding timer to a slot that will gradually change the size, and then I start the timer:

void cForm::expandHorizontally(const QString & str)
{
    ui.Text->setText( str ); 
    connect( &oTimer, SIGNAL(timeout()), this, SLOT(increaseHSize()) );
    cTimer.stop();//if the label is collapsing at the moment, stop it
    disconnect( &cTimer, SIGNAL(timeout()) );
    oTimer.start();//start expanding
}

void cForm::compactHorizontally(const QString &)
{
    connect( &cTimer, SIGNAL(timeout()), this, SLOT(decreaseHSize()) );
    oTimer.stop();
    disconnect( &oTimer, SIGNAL(timeout()) );
    cTimer.start();
}

After that, the label starts changing it's size:

void cForm::increaseHSize()
{
    if( ui.Text->width() < 120 )
    {
        //increase the size a bit if it hasn't reached the bound yet
        ui.Text->setFixedWidth( ui.Text->width() + 10 );
    }
    else
    {
        ui.Text->setFixedWidth( 120 );//Set the desired size
        oTimer.stop();//stop the timer
        disconnect( &oTimer, SIGNAL(timeout()) );//disconnect the timer's signal
    }
}

void cForm::decreaseHSize()
{
    if( ui.Text->width() > 0 )
    {
        ui.Text->setFixedWidth( ui.Text->width() - 10 );
    }
    else
    {
        ui.Text->setFixedWidth( 0 );
        cTimer.stop();
        disconnect( &cTimer, SIGNAL(timeout()) );
    }
}

The problem: Everything works smoothly at first, the label slowly opens and closes. However, if it does so a couple of times, it starts changing the size faster and faster each time (just as if the timer's interval was getting smaller and smaller, but it obviously isn't). Eventually after a couple of openings/closes it just begins to immediately increase it's size up to the bound when I hover the mouse over the button, and immediately collapse to the zero size when the mouse goes away from the button.

What could be the reason for that?

هل كانت مفيدة؟

المحلول

I would suggest that events are waiting to be processed, and the number of queued events increase with time. Maybe because an event is not completely processed between two timer events or due to the other parts of the program.

Why don't you use only one timer? You can go even further, by using only slot for size change events. The other slots are just there for changing what type of change:

void cForm::connectStuff(){
    connect( &oTimer, SIGNAL(timeout()), this, SLOT(changeSize()) );
    connect( 
          ui.Button, 
          SIGNAL(mouseEntered(QString)), 
          this, 
          SLOT(expandHorizontally()) 
    );
    connect( 
          ui.Button, 
          SIGNAL(mouseLeft(QString)), 
          this, 
          SLOT(compactHorizontally()) 
    );
}

void cForm::expandHorizontally(){
      shouldExpand = true;
}

void cForm::compactHorizontally(){
      shouldExpand = false;
}

void cForm::changeSize(){
     if(shouldExpand)
        increaseHSize();//call the function which expand
     else
        decreaseHSize();//call the function which compact
}

نصائح أخرى

According to your code, QTimer's timeout() signal is connected multiple times to the same slot, and multiple connections mean that when the signal is emitted, the slot will be called multiples times too, which would seem as if the timer was accelerating.

To avoid that you can make the connection unique with:

connect( &oTimer, SIGNAL(timeout()), this, SLOT(increaseHSize()), Qt::UniqueConnection);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top