QtQuick中弧度与角度切换管理
在QtQuick中实现角度与弧度的自动切换:
1. 创建角度/弧度管理类 (AngleRadiansManager)
// anglemanager.h
#include <QObject>
#include <cmath>
class AngleManager : public QObject {
Q_OBJECT
Q_PROPERTY(bool useDegrees READ useDegrees WRITE setUseDegrees NOTIFY useDegreesChanged)
public:
explicit AngleManager(QObject *parent = nullptr);
bool useDegrees() const;
void setUseDegrees(bool useDegrees);
// 核心转换函数
Q_INVOKABLE double toDisplayUnit(double value, bool isStoredInRadians) const;
Q_INVOKABLE double fromDisplayUnit(double displayValue, bool storeAsRadians) const;
signals:
void useDegreesChanged();
private:
bool m_useDegrees = true; // 默认显示角度
};
// anglemanager.cpp
#include "anglemanager.h"
AngleManager::AngleManager(QObject *parent) : QObject(parent) {}
bool AngleManager::useDegrees() const { return m_useDegrees; }
void AngleManager::setUseDegrees(bool useDegrees) {
if (m_useDegrees != useDegrees) {
m_useDegrees = useDegrees;
emit useDegreesChanged();
}
}
double AngleManager::toDisplayUnit(double value, bool isStoredInRadians) const {
if (m_useDegrees && isStoredInRadians) {
return qRadiansToDegrees(value); // 弧度 -> 角度
} else if (!m_useDegrees && !isStoredInRadians) {
return qDegreesToRadians(value); // 角度 -> 弧度
}
return value; // 不需要转换
}
double AngleManager::fromDisplayUnit(double displayValue, bool storeAsRadians) const {
if (m_useDegrees && storeAsRadians) {
return qDegreesToRadians(displayValue); // 显示角度 → 存储弧度
} else if (!m_useDegrees && !storeAsRadians) {
return qRadiansToDegrees(displayValue); // 显示弧度 → 存储角度
}
return displayValue; // 不需要转换
}
2. 注册到QML上下文
// main.cpp
#include "anglemanager.h"
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
AngleManager angleManager;
QQmlApplicationEngine engine;
// 注册单例管理类
engine.rootContext()->setContextProperty("angleManager", &angleManager);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
3. QML控件实现
// 切换按钮
Switch {
text: qsTr("角度模式")
checked: angleManager.useDegrees
onToggled: angleManager.setUseDegrees(checked)
}
// 使用示例1: 显示角度值(内部存储为弧度)
TextInput {
property double angleRadians: Math.PI / 4 // 内部始终以弧度存储
text: angleManager.toDisplayUnit(angleRadians, true).toFixed(2)
validator: DoubleValidator {}
onTextEdited: {
var val = parseFloat(text);
if (!isNaN(val)) {
angleRadians = angleManager.fromDisplayUnit(val, true);
}
}
}
// 使用示例2: 显示角度值(内部存储为角度)
TextInput {
property double angleDegrees: 45 // 内部始终以角度存储
text: angleManager.toDisplayUnit(angleDegrees, false).toFixed(2)
validator: DoubleValidator {}
onTextEdited: {
var val = parseFloat(text);
if (!isNaN(val)) {
angleDegrees = angleManager.fromDisplayUnit(val, false);
}
}
}
// 单位标签
Text {
text: angleManager.useDegrees ? "°" : "rad"
}
4. 高级用法 - 创建可重用组件
// SmartAngleInput.qml
Item {
property double value: 0
property bool storeAsRadians: true // 声明内部存储格式
TextInput {
id: inputField
text: angleManager.toDisplayUnit(parent.value, parent.storeAsRadians).toFixed(2)
validator: DoubleValidator {}
onTextEdited: {
var val = parseFloat(text);
if (!isNaN(val)) {
parent.value = angleManager.fromDisplayUnit(val, parent.storeAsRadians);
}
}
}
Text {
anchors.left: inputField.right
anchors.verticalCenter: inputField.verticalCenter
text: angleManager.useDegrees ? "°" : "rad"
}
}
实现说明:
- 统一管理中心:通过
AngleManager单例管理全局显示状态 - 双向转换:
toDisplayUnit(): 将存储值转换为当前显示单位fromDisplayUnit(): 将显示值转换回存储单位
- 数据存储分离:
- 通过bool参数
isStoredInRadians声明数据存储格式 - 控件不需要关心当前显示模式
- 通过bool参数
- 自动响应:
- 当angleManager.useDegrees改变时,所有绑定toDisplayUnit的控件自动更新
- 支持双向绑定:
- 编辑时自动转换回原始存储格式
- 组件化:
- 通过SmartAngleInput封装可重用组件
此方案特点:
- 核心逻辑集中在C++中,性能更优
- QML层保持简洁
- 支持任意类型控件(Slider、Text、Dial等)
- 自动响应单位切换
- 支持不同的数据存储需求(有些数据存弧度,有些存角度)
当用户切换显示模式时,所有控件会自动根据预设的存储格式进行正确转换,并在界面上更新显示值和单位符号。

浙公网安备 33010602011771号