私はスライダーコントロールを持っていて、ユーザーはそれを本当に速くスライドさせているとしましょう。コントロールが変更されたときのコールバックのレート制限
QMLが「新しい値を利用できる」C++コールバックを呼び出す割合を制限することはできますか?
私はスライダーコントロールを持っていて、ユーザーはそれを本当に速くスライドさせているとしましょう。コントロールが変更されたときのコールバックのレート制限
QMLが「新しい値を利用できる」C++コールバックを呼び出す割合を制限することはできますか?
あなたは完全にスライダーをドラッグしている間、更新された値を回避したい場合、あなたはQtのクイックでupdateValueWhileDragging
プロパティを使用することができますが1を制御し、Qtのクイックでlive
プロパティは、Qtのクイックコントロール2.
を制御します図2に示すように、スライダコントロールは、いつでも値をチェックするために呼び出すことができるvalueAt()
機能を有する。
あなたはQMLで独自のスライダーを書いている場合は、例えば、Timer
を使用して変更信号の排出を制限することができます:
property int value
readonly property int actualValue: // some calculation...
Timer {
running: slider.pressed
interval: 200
repeat: true
onTriggered: slider.value = slider.actualValue
}
ここでは、一般的なC++だ - どんなQObject
で動作する側のソリューションは:
// https://github.com/KubaO/stackoverflown/tree/master/questions/qml-rate-limter-42284163
#include <QtCore>
class PropertyRateLimiter : public QObject {
Q_OBJECT
qint64 msecsPeriod{500};
const QByteArray property;
bool dirty{};
QVariant value;
QElapsedTimer time;
QBasicTimer timer;
QMetaMethod slot = metaObject()->method(metaObject()->indexOfSlot("onChange()"));
void signal() {
if (time.isValid()) time.restart(); else time.start();
if (dirty)
emit valueChanged(value, parent(), property);
else
timer.stop();
dirty = false;
}
Q_SLOT void onChange() {
dirty = true;
value = parent()->property(property);
auto elapsed = time.isValid() ? time.elapsed() : 0;
if (!time.isValid() || elapsed >= msecsPeriod)
signal();
else
if (!timer.isActive())
timer.start(msecsPeriod - elapsed, this);
}
void timerEvent(QTimerEvent *event) override {
if (timer.timerId() == event->timerId())
signal();
}
public:
PropertyRateLimiter(const char * propertyName, QObject * parent) :
QObject{parent}, property{propertyName}
{
auto mo = parent->metaObject();
auto property = mo->property(mo->indexOfProperty(this->property));
if (!property.hasNotifySignal())
return;
connect(parent, property.notifySignal(), this, slot);
}
void setPeriod(int period) { msecsPeriod = period; }
Q_SIGNAL void valueChanged(const QVariant &, QObject *, const QByteArray & name);
};
#include "main.moc"
そして、それのためのテストハーネス:
#include <QtQuick>
const char qmlData[] =
R"__end(
import QtQuick 2.6
import QtQuick.Controls 2.0
ApplicationWindow {
minimumWidth: 300
minimumHeight: 250
visible: true
Column {
anchors.fill: parent
Slider { objectName: "slider" }
Label { objectName: "label" }
}
}
)__end";
int main(int argc, char ** argv) {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app{argc, argv};
QQmlApplicationEngine engine;
engine.loadData(QByteArray::fromRawData(qmlData, sizeof(qmlData)-1));
auto window = engine.rootObjects().first();
auto slider = window->findChild<QObject*>("slider");
auto label = window->findChild<QObject*>("label");
PropertyRateLimiter limiter("position", slider);
QObject::connect(&limiter, &PropertyRateLimiter::valueChanged, [&](const QVariant & val){
label->setProperty("text", val);
});
return app.exec();
}
私はQMLについて何も知りません。このコンテキストでは、このソリューションはC++コールバックでそのレート制限を実装しているようです。 QML文脈でそれを行うことは可能ですか?私は、ユーザーがスライダーを素早く切り替える場合の経過時間切れの前に、あらゆる種類の関数呼び出しを避けようとしています。 – Adrian
これは、JavaScriptコードで同じコードを実行しなければならないので、QMLで行うのが遅くなります。 QMLはC++の上に構築されており、そのすべての機能はC++で実装されているため、C++経由でのインタフェースは最も高速です。また、Qtではこれらをコールバックではなくスロットと呼びます。 –