<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[I implemented a debounce connnect to prevent sending signals too frequently, please help to check whether this code will cause bugs.]]></title><description><![CDATA[<pre><code>#include &lt;QTimer&gt;
#include &lt;type_traits&gt;
#include &lt;tuple&gt;
class Debounce
{
	template &lt;typename T&gt;
	struct lambda_traits : lambda_traits&lt;decltype(&amp;T::operator())&gt; {};

	template &lt;typename ClassType, typename ReturnType, typename... Args&gt;
	struct lambda_traits&lt;ReturnType(ClassType::*)(Args...) const&gt;
	{
		static const std::size_t arity = sizeof...(Args);
	};

	template&lt;typename Func, std::size_t... Is, typename... Args&gt;
	void static call_slot(Func slot, std::index_sequence&lt;Is...&gt;, Args&amp;&amp;... args) {
		slot(std::get&lt;Is&gt;(std::forward_as_tuple(std::forward&lt;Args&gt;(args)...))...);
	}
public:
	template &lt;typename Func1, typename Func2&gt;
	static inline QMetaObject::Connection
		connect(const typename QtPrivate::FunctionPointer&lt;Func1&gt;::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection)
	{
		QTimer* timer = new QTimer((QObject*)sender);
		timer-&gt;setSingleShot(true);
		auto func3 = new std::function&lt;void()&gt;;
		QObject::connect(sender, signal, timer, [=](auto&amp;&amp;... args) {*func3 =
			[=]() {call_slot(slot, std::make_index_sequence&lt;lambda_traits&lt;Func2&gt;::arity&gt;(), (args)...);};
			timer-&gt;start(200); });
		return QObject::connect(timer, &amp;QTimer::timeout, context, [=]() {(*func3)(); }, type);
	}
};
#include &lt;QApplication&gt;
#include &lt;QSlider&gt;
#include &lt;QDoubleSpinBox&gt;

int main(int argc, char* argv[])
{
	QApplication app(argc, argv);
	auto w = new QWidget();
	auto sl = new QSlider(Qt::Horizontal, w);
	auto dsp = new QDoubleSpinBox(w);
	w-&gt;show();
	sl-&gt;move(30, 30);
	w-&gt;resize(200, 100);

	Debounce::connect(sl, &amp;QSlider::valueChanged, sl, []() {printf("QSlider1 \n "); });
	Debounce::connect(sl, &amp;QSlider::valueChanged, sl, [](int v) {printf("QSlider2  %d  \n", v); });
	Debounce::connect(dsp, QOverload&lt;double&gt;::of(&amp;QDoubleSpinBox::valueChanged), dsp, [=](double v) {printf("QDoubleSpinBox %f  \n", v);  emit sl-&gt;rangeChanged(0, v); });
	Debounce::connect(sl, &amp;QSlider::rangeChanged, sl, [](int v0, int v1) {printf("rangeChanged   %d  %d\n", v0, v1); });
	return app.exec();
}
</code></pre>
]]></description><link>https://forum.qt.io/topic/157973/i-implemented-a-debounce-connnect-to-prevent-sending-signals-too-frequently-please-help-to-check-whether-this-code-will-cause-bugs</link><generator>RSS for Node</generator><lastBuildDate>Thu, 06 Aug 2026 02:40:33 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/157973.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 30 Jul 2024 06:56:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to I implemented a debounce connnect to prevent sending signals too frequently, please help to check whether this code will cause bugs. on Thu, 01 Aug 2024 13:02:25 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/simonschroeder">@<bdi>SimonSchroeder</bdi></a> I added the Throttle class to implement low-frequency send signals</p>
<pre><code>#include &lt;type_traits&gt;
#include &lt;tuple&gt;
#include &lt;QTimer&gt;
#include &lt;QCoreApplication&gt;
namespace QtUtility
{
	template &lt;typename T&gt;
	struct lambda_traits : lambda_traits&lt;decltype(&amp;T::operator())&gt; {};

	template &lt;typename ClassType, typename ReturnType, typename... Args&gt;
	struct lambda_traits&lt;ReturnType(ClassType::*)(Args...) const&gt;
	{
		static const std::size_t arity = sizeof...(Args);
	};

	template&lt;typename Func, std::size_t... Is, typename... Args&gt;
	void static call_slot(Func slot, std::index_sequence&lt;Is...&gt;, Args&amp;&amp;... args) {
		slot(std::get&lt;Is&gt;(std::forward_as_tuple(std::forward&lt;Args&gt;(args)...))...);
	}
	class MyTimer : public QTimer
	{
	public:
		using QTimer::QTimer;
		std::function&lt;void()&gt; func;
	};
}
class Debounce : QObject
{
public:
	int interval = 200;
	Debounce(int v, QObject* parent = NULL)
	{
		interval = v;
		setParent(parent ? parent : QCoreApplication::instance());
	}
	template &lt;typename Func1, typename Func2&gt;
	inline QMetaObject::Connection
		connect(const typename QtPrivate::FunctionPointer&lt;Func1&gt;::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection)
	{
		using namespace QtUtility;
		auto timer = new MyTimer((QObject*)sender);
		timer-&gt;setSingleShot(true);
		QObject::connect(sender, signal, timer, [=](auto&amp;&amp;... args) {timer-&gt;func =
			[=]() {call_slot(slot, std::make_index_sequence&lt;lambda_traits&lt;Func2&gt;::arity&gt;(), (args)...); };
		timer-&gt;start(interval); });
		return QObject::connect(timer, &amp;QTimer::timeout, context, [=]() {timer-&gt;func(); }, type);
	}
};
class Throttle : QObject
{
public:
	int interval = 200;
	Throttle(int v, QObject* parent = NULL)
	{
		interval = v;
		setParent(parent ? parent : QCoreApplication::instance());
	}
	template &lt;typename Func1, typename Func2&gt;
	inline QMetaObject::Connection
		connect(const typename QtPrivate::FunctionPointer&lt;Func1&gt;::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection)
	{
		using namespace QtUtility;
		auto timer = new MyTimer((QObject*)sender);
		timer-&gt;setSingleShot(true);
		QObject::connect(sender, signal, timer, [=](auto&amp;&amp;... args) {timer-&gt;func =
			[=]() {call_slot(slot, std::make_index_sequence&lt;lambda_traits&lt;Func2&gt;::arity&gt;(), (args)...); };
		if (!timer-&gt;isActive())
			timer-&gt;start(interval); });
		return QObject::connect(timer, &amp;QTimer::timeout, context, [=]() {timer-&gt;func(); }, type);
	}
};
#include &lt;QApplication&gt;
#include &lt;QSlider&gt;
#include &lt;QDoubleSpinBox&gt;
#include &lt;QWheelEvent&gt;
int main(int argc, char* argv[])
{
	QApplication app(argc, argv);
	auto w = new QWidget();
	auto sl = new QSlider(Qt::Horizontal, w);
	auto dsp = new QDoubleSpinBox(w);
	w-&gt;show();
	sl-&gt;move(30, 30);
	w-&gt;resize(200, 100);
	{
		auto db = new Debounce(200);
		auto thr = new Throttle(200);
		QObject::connect(dsp, QOverload&lt;double&gt;::of(&amp;QDoubleSpinBox::valueChanged), dsp, [=](double v) {
			emit sl-&gt;rangeChanged(0, v); });
		db-&gt;connect(dsp, QOverload&lt;double&gt;::of(&amp;QDoubleSpinBox::valueChanged), dsp, [=](double v) {
			printf("QDoubleSpinBox %f  \n", v); });
		db-&gt;connect(sl, &amp;QSlider::valueChanged, sl, []() {printf("QSlider1 \n "); });
		db-&gt;connect(sl, &amp;QSlider::valueChanged, sl, [](int v) {printf("QSlider2  %d  \n", v); });
		thr-&gt;connect(sl, &amp;QSlider::rangeChanged, sl, [](int v0, int v1) {printf("rangeChanged   %d  %d\n", v0, v1); });
	}
	return app.exec();
}
</code></pre>
]]></description><link>https://forum.qt.io/post/806349</link><guid isPermaLink="true">https://forum.qt.io/post/806349</guid><dc:creator><![CDATA[John Van]]></dc:creator><pubDate>Thu, 01 Aug 2024 13:02:25 GMT</pubDate></item><item><title><![CDATA[Reply to I implemented a debounce connnect to prevent sending signals too frequently, please help to check whether this code will cause bugs. on Thu, 01 Aug 2024 11:18:31 GMT]]></title><description><![CDATA[<p dir="auto">This will most likely fully debounce your signals. You should think about this if this is actually what you want. If there is no pause of at least 200ms between emitted signals, the slot will never be executed. A common solution is to use a second timer with a longer timeout which will not be restarted for every signal emitted, but only if it is not running. On timeout, the second timer will also stop your current timer, such that the slot is not executed twice. It is up to you, which kind of debounce you want.</p>
]]></description><link>https://forum.qt.io/post/806342</link><guid isPermaLink="true">https://forum.qt.io/post/806342</guid><dc:creator><![CDATA[SimonSchroeder]]></dc:creator><pubDate>Thu, 01 Aug 2024 11:18:31 GMT</pubDate></item><item><title><![CDATA[Reply to I implemented a debounce connnect to prevent sending signals too frequently, please help to check whether this code will cause bugs. on Tue, 30 Jul 2024 16:36:01 GMT]]></title><description><![CDATA[<p dir="auto">I haven’t had a look at your code.<br />
But I am using <a href="https://github.com/KDABLabs/KDToolBox/tree/master/qt/KDSignalThrottler" target="_blank" rel="noopener noreferrer nofollow ugc">KDSignalThrottler</a> for signal debouncing. Works great so far and maybe it is of use for you.</p>
]]></description><link>https://forum.qt.io/post/806208</link><guid isPermaLink="true">https://forum.qt.io/post/806208</guid><dc:creator><![CDATA[DerReisende]]></dc:creator><pubDate>Tue, 30 Jul 2024 16:36:01 GMT</pubDate></item></channel></rss>