QT5 平滑地更改整数文本

QT5 Change integer text smoothly

本文关键字:整数 文本 平滑 QT5      更新时间:2023-10-16

我不知道该技术的术语是否顺利,但听起来最容易理解。因此,让我们解释一下我想要什么。

我有两个按钮:一个 + 和一个 - 中间有一个数字 10。

我的范围在 1 到 300 之间。我不希望用户点击 289 次转到 300 次。我希望当用户将我的案例手指放在 + 按钮上时,例如 5 秒。并且改变得非常快。

是否可以使用 QPushButton 的单击插槽来实现,或者我需要找到另一个解决方案并编写自定义小部件。并且确实已经实现了一些功能或小部件

此功能已经在Qt中实现。

启用QPushButtonautoRepeat属性。按下按钮时,它会定期触发按钮的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;
};

您也可以使用 mousePressEventmouseReleaseEvent 对普通小部件执行相同的操作。它可能对自定义样式的小部件很有用,并避免与内部布局相关的问题:

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