【问题标题】:QTimer becomes faster with each start/stopQTimer 在每次启动/停止时变得更快
【发布时间】:2012-09-21 09:50:37
【问题描述】:

我正在使用QTimer 来平滑更改标签的大小:当我将鼠标悬停在按钮上时它应该会慢慢增长,当鼠标离开按钮时它会慢慢折叠(减小它的大小直到消失) .

我的表单类中有两个计时器:

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

在表单的构造函数中,我正在设置计时器的值并将按钮的 mouseOvermouseOut 信号连接到表单的插槽:

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)) );

现在,在这些插槽中,我将相应的计时器连接到将逐渐改变大小的插槽,然后我启动计时器:

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();
}

之后,标签开始改变它的大小:

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()) );
    }
}

问题:一开始一切正常,标签慢慢打开和关闭。但是,如果它这样做了几次,它每次都会开始越来越快地改变大小(就像计时器的间隔越来越小,但显然不是)。最终,在几次打开/关闭之后,当我将鼠标悬停在按钮上时,它才开始立即将它的大小增加到边界,然后立即折叠到零大小当鼠标离开按钮时。

这可能是什么原因?

【问题讨论】:

  • 我们能看到compactHorizontally(QString) 方法和它对应的size 'shrinker' 方法吗?我有一种预感,它不是QTimer,而是与大小调整逻辑有关。此外,QPropertyAnimation 正是为此目的而设计的,它让生活变得更轻松。
  • @cmannett85,更新了问题。我这样做是为了学习目的,这就是我自己实现它的原因
  • 哪个类提供mouseEntered信号??
  • @UmNyobe,我的类继承自QPushButton,唯一的目的就是这样做:void cHoverButton::enterEvent(QEvent *) { emit mouseEntered( accessibleName() ); }
  • 这是一个重要的说明。添加它

标签: c++ qt qtimer


【解决方案1】:

我建议事件正在等待处理,排队事件的数量会随着时间的推移而增加。可能是因为一个事件在两个定时器事件之间没有被完全处理,或者是由于程序的其他部分。

你为什么不只使用一个计时器?您可以走得更远,只使用插槽来进行大小更改事件。其他插槽仅用于更改更改类型:

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
}

【讨论】:

  • 谢谢,改成 1 个计时器有帮助。不过这很有趣,我没想到它会表现得如此……
  • 我同意。我也需要在 qt 事件上做作业,这对我来说仍然是一个灰色地带。
【解决方案2】:

根据您的代码,QTimertimeout() 信号多次连接到同一个槽,多次连接意味着当信号发出时,槽也会被多次调用,这看起来像如果计时器正在加速。

为避免这种情况,您可以通过以下方式使连接独一无二:

connect( &oTimer, SIGNAL(timeout()), this, SLOT(increaseHSize()), Qt::UniqueConnection);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多