QT5如何平滑地更改整数文本

3
我不确定这种技术的术语是否流畅,但它最易懂。因此,让我们解释一下我的需求。
我有两个按钮:一个+和一个-,中间有一个数字10。
我的范围在1到300之间。我不希望用户点击289次才能到达300。我希望当用户按住+按钮时,可以快速地增加数字,例如5秒钟内增加。并且要能快速改变。
是否可以通过QPushButton的clicked SLOT来实现这个功能?或者我需要找到另一个解决方案并编写自定义小部件。还有,是否已经有某些函数或小部件实现了这个功能?

你可能想使用一个计时器,它会在按钮按下后立即启动。它会一直计数,直到按钮被释放。 - vahancho
一个计时器里面再放另一个计时器,第一秒慢速运行,下一秒快速运行,可以实现这个功能吗? - evelikov92
您可以使用单个计时器,在一段时间后减少其间隔。 - vahancho
1
另一个选项是使用 QPropertyAnimation。您可以配置其速度如何变化。请参阅:QEasingCurve - vahancho
一定要提供键盘输入选项(例如QLineEdit),否则您可能会因为不必要的繁琐输入方式而使用户感到沮丧。在这里,QSlider或QDial也可能很有用。 - Jeremy Friesner
@JeremyFriesner 的描述没有输入。该应用程序将在触摸屏上运行,我不知道其他人的情况,但我真的很讨厌在虚拟键盘上打字母。使用 + 和 - 也更好地放置最小和最大值。 - evelikov92
2个回答

2

这个功能已经在Qt中实现了。

启用您的QPushButtonautoRepeat属性。当按钮被按下时,它会定期触发clicked信号。

像往常一样连接一个槽即可。


Translated:

1
创建一个小部件,包含两个按钮(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;
};

您也可以通过使用 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;
};

我会检查第一个例子。谢谢。 - evelikov92

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接