diff --git a/src/app/panels/columns/CategorySection.cpp b/src/app/panels/columns/CategorySection.cpp index d26ad70..d329cdb 100644 --- a/src/app/panels/columns/CategorySection.cpp +++ b/src/app/panels/columns/CategorySection.cpp @@ -475,10 +475,23 @@ void CategorySection::showPlaneZPopup(QToolButton* host) { sld->setToolTip(QStringLiteral("平面高程 z(米)")); auto syncLabel = [lab](int v) { lab->setText(QStringLiteral("平面 z:%1 米").arg(v)); }; syncLabel(sld->value()); + // 发射防抖:valueChanged 在拖动期逐整数步触发,每步直发 planeZChanged 会引发数十次 + // removeDataset+add2DDatasetAsync 抖动重摆(生产异步路径 loadingDs_ 守护会丢中间帧→足迹滞后于陈旧 z)。 + // 故 label/lastPlaneZ_ 即时回显,但 planeZChanged 经单发 QTimer(150ms)合并——每次变更重启,停手后只发一次终值。 + // 定时器 parent=this(CategorySection),存活于 modal popup(menu.exec)之外,即便 popup 已销毁也能安全发射终值。 + if (!planeZTimer_) { + planeZTimer_ = new QTimer(this); + planeZTimer_->setSingleShot(true); + planeZTimer_->setInterval(150); + connect(planeZTimer_, &QTimer::timeout, this, [this]() { + emit planeZChanged(QString::fromStdString(desc_.id), pendingPlaneZ_); + }); + } connect(sld, &QSlider::valueChanged, this, [this, syncLabel](int v) { lastPlaneZ_ = v; syncLabel(v); - emit planeZChanged(QString::fromStdString(desc_.id), static_cast(v)); + pendingPlaneZ_ = static_cast(v); + planeZTimer_->start(); // 重启防抖窗口:覆盖拖动、键盘、点轨——停手后一次性发射 }); lay->addWidget(lab); lay->addWidget(sld); diff --git a/src/app/panels/columns/CategorySection.hpp b/src/app/panels/columns/CategorySection.hpp index 5cb9285..45e0675 100644 --- a/src/app/panels/columns/CategorySection.hpp +++ b/src/app/panels/columns/CategorySection.hpp @@ -92,6 +92,8 @@ private: QTimer* spinTimer_ = nullptr; // 驱动 busy 行 spinner 旋转(有 busy 行时运行) int spinAngle_ = 0; // 当前 spinner 角度(度) double lastPlaneZ_ = 0.0; // 上次 z 值滑块设定的平面高程(重开 popup 时回显,无则 0) + QTimer* planeZTimer_ = nullptr; // z 值滑块发射防抖:拖动/键盘/点轨期合并为停手后一次重摆(owned by this,存活于 popup 之外) + double pendingPlaneZ_ = 0.0; // 防抖待发的平面 z(定时器到点时取此值发射 planeZChanged) }; } // namespace geopro::app