I don't know do the termin of that technology is smoothly but is sound most understandable. So let's explain what I want.
I have two buttons: One + and One - and in the middle one number 10.
My range is between 1 and 300. I don't want the user to click 289 times to go to 300. I want when user keep for my case finger on + button to go for example 5 seconds. And change it really fast.
Is it possible to implemented with clicked SLOT of the QPushButton or I need to find another solution and write custom widget. And do is have some function or widget already implemented
Create a widget containing two buttons (add and sub) and a label. Use QPushButton::pressed
signal to know when a button is pressed and QPushButton::released
.
When a button is pressed, define the direction (sub or add) and trigger a timer with a high initial interval. Each time the timer is elapsed ( QTimer::timeout
), increment/decrement the value regarding to the direction and decrease the interval of your timer.
A quick example:
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;
};
You can also do the same thing with a plain widget by using mousePressEvent
and mouseReleaseEvent
. It could be useful for custom-style widgets and avoid the issues related to the inner layout:
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;
};
This functionality is already implemented in Qt.
Enable the autoRepeat
property of your QPushButton
. It will trigger the clicked
signal of your button periodically while it is pressed.
Just connect a slot to it as usual.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.