我不知道该技术的术语是否顺利,但听起来最容易理解。因此,让我们解释一下我想要什么。
我有两个按钮:一个 + 和一个 - 中间有一个数字 10。
我的范围在 1 到 300 之间。我不希望用户点击 289 次转到 300 次。我希望当用户将我的案例手指放在 + 按钮上时,例如 5 秒。并且改变得非常快。
是否可以使用 QPushButton 的单击插槽来实现,或者我需要找到另一个解决方案并编写自定义小部件。并且确实已经实现了一些功能或小部件
此功能已经在Qt中实现。
启用QPushButton
的autoRepeat
属性。按下按钮时,它会定期触发按钮的clicked
信号。
只需像往常一样将插槽连接到它。
创建一个包含两个按钮(添加和订阅(和一个标签的小部件。使用QPushButton::pressed
信号知道何时按下按钮并QPushButton::released
。
按下按钮时,定义方向(sub 或 add(并触发具有高初始间隔的计时器。每次经过计时器时(QTimer::timeout
(,递增/递减有关方向的值并减少计时器的间隔。
举个简单的例子:
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;
};