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號