165 lines
5.6 KiB
C++
165 lines
5.6 KiB
C++
#include "paramcontrol.h"
|
||
#include "numpaddialog.h"
|
||
#include "global.h"
|
||
#include <QVBoxLayout>
|
||
#include <QHBoxLayout>
|
||
#include <QLabel>
|
||
#include <QLineEdit>
|
||
#include <QPushButton>
|
||
#include <QKeyEvent>
|
||
#include "global.h"
|
||
|
||
ParamControl::ParamControl(const QString& name, const QString& unit,
|
||
double step, double min, double max,
|
||
bool withSave, bool withFactory, QWidget* parent)
|
||
: QWidget(parent), m_name(name), m_unit(unit),
|
||
m_step(step), m_min(min), m_max(max), m_value(min)
|
||
{
|
||
QVBoxLayout* lay = new QVBoxLayout(this);
|
||
lay->setContentsMargins(12, 8, 12, 8);
|
||
lay->setSpacing(6);
|
||
|
||
// 参数名
|
||
m_nameLabel = new QLabel(name, this);
|
||
m_nameLabel->setProperty("sub", true);
|
||
m_nameLabel->setStyleSheet(QString("color:%1;font-size:40px;").arg(C::TEXT_SUB));
|
||
lay->addWidget(m_nameLabel);
|
||
|
||
// 数值输入框 + 单位(同一行;框内只显示数值)
|
||
m_valRow = new QHBoxLayout();
|
||
m_valRow->setSpacing(12);
|
||
|
||
m_valueEdit = new QLineEdit(this);
|
||
m_valueEdit->setReadOnly(true);
|
||
m_valueEdit->setAlignment(Qt::AlignCenter);
|
||
m_valueEdit->setFocusPolicy(Qt::StrongFocus);
|
||
m_valueEdit->setFixedWidth(150); // 输入框长度(按需调整)
|
||
m_valueEdit->setStyleSheet("font-size:40px;font-weight:700;");
|
||
m_valueEdit->installEventFilter(this);
|
||
m_valRow->addStretch(0); // 行首弹性空间:setCentered(true) 时置 1,数值行即居中
|
||
m_valRow->addWidget(m_valueEdit);
|
||
|
||
m_unitLabel = new QLabel(unit, this);
|
||
m_unitLabel->setStyleSheet(QString("color:%1;font-size:40px;").arg(C::TEXT_SUB));
|
||
// 同一行右侧还有按钮时,给单位固定占位,保证各参数的按钮 x 一致
|
||
// (110 取全项目最长单位“L/min”在 40px 字号下的宽度约 101px)
|
||
if (withSave || withFactory)
|
||
m_unitLabel->setFixedWidth(110);
|
||
m_valRow->addWidget(m_unitLabel);
|
||
|
||
// 保存 / 恢复出厂值(可选):跟在单位后面,与输入框同一行、整体左对齐
|
||
if (withSave) {
|
||
m_save = new QPushButton("保存", this);
|
||
m_save->setProperty("variant", "primary");
|
||
m_save->setFixedSize(140, 60); // 固定宽高,不再随布局拉伸
|
||
connect(m_save, &QPushButton::clicked, this, &ParamControl::saveClicked);
|
||
m_valRow->addWidget(m_save);
|
||
}
|
||
if (withFactory) {
|
||
m_factory = new QPushButton("恢复出厂值", this);
|
||
m_factory->setMinimumHeight(56);
|
||
connect(m_factory, &QPushButton::clicked, this, &ParamControl::factoryResetClicked);
|
||
m_valRow->addWidget(m_factory);
|
||
}
|
||
|
||
m_valRow->addStretch(1);
|
||
lay->addLayout(m_valRow);
|
||
|
||
refresh();
|
||
}
|
||
|
||
void ParamControl::setValue(double v)
|
||
{
|
||
m_value = qBound(m_min, v, m_max);
|
||
refresh();
|
||
}
|
||
|
||
QWidget* ParamControl::editor() const
|
||
{
|
||
return m_valueEdit;
|
||
}
|
||
|
||
void ParamControl::setEnabled(bool enabled)
|
||
{
|
||
QWidget::setEnabled(enabled);
|
||
}
|
||
|
||
void ParamControl::setCentered(bool on)
|
||
{
|
||
m_nameLabel->setAlignment(on ? Qt::AlignCenter : (Qt::AlignLeft | Qt::AlignVCenter));
|
||
m_valRow->setStretch(0, on ? 1 : 0); // 行首弹性空间与行尾均分 → 整行居中(含保存按钮)
|
||
}
|
||
|
||
// 旋钮接口:steps > 0 调大、< 0 调小(每格 = m_step,自动钳位到 [min, max])
|
||
// 目前由数值框上的 ↑/↓ 键驱动,后续接面板机械旋钮也走这里
|
||
void ParamControl::adjustByKnob(int steps)
|
||
{
|
||
if (steps == 0)
|
||
return;
|
||
const double old = m_value;
|
||
setValue(old + steps * m_step);
|
||
if (m_value != old)
|
||
emit valueChanged(m_value);
|
||
}
|
||
|
||
// 点击数值框 / 空格 → 弹出数字键盘(面板靠左、不透明度 80%);↑/↓ → 每档加减一次
|
||
bool ParamControl::eventFilter(QObject* obj, QEvent* ev)
|
||
{
|
||
if (obj == m_valueEdit) {
|
||
if (ev->type() == QEvent::MouseButtonPress) {
|
||
openNumPad();
|
||
return true;
|
||
}
|
||
if (ev->type() == QEvent::KeyPress) {
|
||
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
|
||
const int k = ke->key();
|
||
if (Keys::space(k)) {
|
||
openNumPad();
|
||
return true;
|
||
}
|
||
// 旋钮档:↑ 加一档、↓ 减一档(每档 = m_step)。Tab/Shift+Tab 走焦点链,
|
||
// 各不重叠;按住方向键由按键自动重复继续调
|
||
if (Keys::up(k)) {
|
||
adjustByKnob(1);
|
||
return true;
|
||
}
|
||
if (Keys::down(k)) {
|
||
adjustByKnob(-1);
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return QWidget::eventFilter(obj, ev);
|
||
}
|
||
|
||
void ParamControl::openNumPad()
|
||
{
|
||
NumPadDialog dlg(window()); // 以顶层窗口为父:遮罩覆盖整屏
|
||
dlg.setParamMode(true); // 参数模式:回显显示实际数字,“清除”换成“小数点”
|
||
dlg.setCompact(true); // 紧凑尺寸(不影响密码页的大键盘)
|
||
dlg.setAnchorWidget(m_valueEdit, 20); // 面板贴在输入框左侧 20px 处弹出
|
||
dlg.setMaxLen(6);
|
||
dlg.setValue(m_step < 1.0 ? QString::number(m_value, 'f', 1)
|
||
: QString::number(m_value, 'f', 0));
|
||
if (dlg.exec() != QDialog::Accepted)
|
||
return;
|
||
|
||
bool ok = false;
|
||
const double v = dlg.value().toDouble(&ok);
|
||
if (!ok)
|
||
return;
|
||
const double old = m_value;
|
||
setValue(v);
|
||
if (m_value != old)
|
||
emit valueChanged(m_value);
|
||
}
|
||
|
||
void ParamControl::refresh()
|
||
{
|
||
// 框内只显示数值(单位在框后面的标签里)
|
||
if (m_step < 1.0)
|
||
m_valueEdit->setText(QString::number(m_value, 'f', 1));
|
||
else
|
||
m_valueEdit->setText(QString::number(m_value, 'f', 0));
|
||
}
|