创建一个小部件,包含两个按钮(add和sub)和一个标签。使用信号来检测按钮是否被按下,并使用信号来检测按钮是否被释放。
当按下一个按钮时,确定方向(sub或add),并触发一个具有高初始间隔的计时器。每次计时器经过(),根据方向增加/减少值,并减少计时器的间隔。
快速示例:
class SpinBox: public QWidget
{
Q_OBJECT
public:
SpinBox(QWidget* parent=nullptr): QWidget(parent),
value(0),
min(0),
max(500),
direction(Forward),
timer(new QTimer(this)),
addButton(new QPushButton("+")),
subButton(new QPushButton("-")),
text(new QLabel("0"))
{
timer->setInterval(500);
connect(addButton, &QPushButton::pressed, this, &SpinBox::forward);
connect(subButton, &QPushButton::pressed, this, &SpinBox::backward);
connect(addButton, &QPushButton::released, timer, &QTimer::stop);
connect(subButton, &QPushButton::released, timer, &QTimer::stop);
connect(timer, &QTimer::timeout, this, &SpinBox::updateValue);
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(subButton);
layout->addWidget(text);
layout->addWidget(addButton);
}
private slots:
void updateValue()
{
if (direction == Forward)
{
++value;
if (value == max)
timer->stop();
}
else
{
--value;
if (value == min)
timer->stop();
}
text->setText(QString::number(value));
timer->setInterval(std::max(10.0, float(timer->interval()) * 0.9));
update();
}
void backward()
{
direction = Backward;
timer->start();
}
void forward()
{
direction = Forward;
timer->start();
}
private:
enum Direction
{
Forward,
Backward
};
int value;
int min;
int max;
Direction direction;
QTimer* timer;
QPushButton* addButton;
QPushButton* subButton;
QLabel* text;
};
您也可以通过使用 mousePressEvent
和 mouseReleaseEvent
处理纯小部件来完成相同的操作。这对于自定义样式小部件非常有用,并避免与内部布局相关的问题:
class SpinBox: public QWidget
{
Q_OBJECT
public:
SpinBox(QWidget* parent=nullptr): QWidget(parent),
value(0),
min(0),
max(500),
direction(Forward),
timer(new QTimer(this))
{
timer->setInterval(500);
connect(timer, &QTimer::timeout, this, &SpinBox::updateValue);
}
private slots:
void updateValue()
{
if (direction == Forward)
{
++value;
if (value == max)
timer->stop();
}
else
{
--value;
if (value == min)
timer->stop();
}
timer->setInterval(std::max(10.0, float(timer->interval()) * 0.9));
update();
}
private:
enum Direction
{
Forward,
Backward
};
virtual void paintEvent(QPaintEvent* event) override
{
QPainter painter(this);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::gray);
painter.drawRect(subButtonRect());
painter.drawRect(addButtonRect());
painter.setPen(Qt::black);
painter.setFont(QFont("Helvetica", 20));
painter.drawText(addButtonRect(), Qt::AlignCenter, "+");
painter.drawText(subButtonRect(), Qt::AlignCenter, "-");
painter.drawText(textRect(), Qt::AlignCenter, QString::number(value));
}
QRect addButtonRect()
{
return QRect(width() - 30, 0, 30, height());
}
QRect subButtonRect()
{
return QRect(0, 0, 30, height());
}
QRect textRect()
{
return QRect(30, 0, width() - 30 * 2, height());
}
virtual void mousePressEvent(QMouseEvent* event) override
{
if (addButtonRect().contains(event->pos()))
{
direction = Forward;
}
else if (subButtonRect().contains(event->pos()))
{
direction = Backward;
}
else
{
return;
}
timer->start();
}
virtual void mouseReleaseEvent(QMouseEvent* event) override
{
timer->stop();
timer->setInterval(500);
}
int value;
int min;
int max;
Direction direction;
QTimer* timer;
};
QPropertyAnimation
。您可以配置其速度如何变化。请参阅:QEasingCurve
。 - vahancho