问:如何将QSpinBox / QDoubleSpinBox设置为角度值?

时间:2018-02-24 13:20:25

标签: qt pyqt

QSpinBox / QDoubleSpinBox默认为十进制值。是否可以将十进制更改为角度?

UPDATE>请看图片。这是我想在QSpinBox / QDoubleSpinBox中获得的效果。

enter image description here

2 个答案:

答案 0 :(得分:1)

首先 - 使用单个旋转框来操纵这样的值是不适用的,因为它代表了一个重要的范围。从用户体验的角度来看,每个组件的专用旋转框都会更容易。

第二 - 如果你仍然坚持使用单个旋转框,Qt没有一个可以开箱即用的小部件。但是,您可以轻松扩展QDoubleSpinBox并重载textFromValue()方法,该方法决定了旋转框显示的文本,然后您可以根据您拥有的任何原始数据组合字符串值。代表地点。

答案 1 :(得分:0)

是的,这是可能的。只需覆盖valueFromTexttextFromValuevalidate(可选fixup)。

  • textFromValue应该很容易
  • valueFromTextvalidate需要解析功能,因此请为其提取常用方法。
  • fixup仅在您知道如何纠正用户错误以及在某些情况下validate何时返回QValidator::Intermediate时使用。

请参阅documentation

这是我的解决方案C ++ 11:

#ifndef DEGREESPINBOX_H
#define DEGREESPINBOX_H

#include <QDoubleSpinBox>

class DegreeSpinBox : public QDoubleSpinBox
{
    Q_OBJECT
public:
    using QDoubleSpinBox::QDoubleSpinBox;

    QString textFromValue(double value) const override;
    double valueFromText(const QString &text) const override;
    QValidator::State validate(QString &text, int &pos) const override;

private:
    static void extractDegMinSecFrom(double value,
                                     int *degrees,
                                     int *minutes,
                                     double *seconds);

    static bool parse(QString str, double *result);
    static bool areSeparatorsValid(QChar deg, QChar min, QChar sec);
};

#endif // DEGREESPINBOX_H

cpp文件

#include "degreespinbox.h"
#include <QTextStream>
#include <cmath>

QString DegreeSpinBox::textFromValue(double value) const {
    int degrees, minutes;
    double seconds;
    extractDegMinSecFrom(value, &degrees, &minutes, &seconds);
    return QString(tr("%1° %2′ %3″"))
            .arg(degrees).arg(minutes).arg(seconds);
}

double DegreeSpinBox::valueFromText(const QString &text) const {
    double result = 0;
    auto ok = parse(text, &result);
    Q_ASSERT(ok);
    return result;
}

QValidator::State DegreeSpinBox::validate(QString &text, int &pos) const {
    Q_UNUSED(pos)
    return parse(text, nullptr) ? QValidator::Acceptable : QValidator::Invalid;
}

void DegreeSpinBox::extractDegMinSecFrom(double value,
                                         int *degrees,
                                         int *minutes,
                                         double *seconds) {
    Q_ASSERT(degrees);
    Q_ASSERT(minutes);
    Q_ASSERT(seconds);
    double degreesDouble;
    double minutesDouble = std::modf(value, &degreesDouble) * 60;
    *degrees = static_cast<int>(degreesDouble);
    *seconds = std::modf(minutesDouble, &minutesDouble) * 60;
    *minutes = static_cast<int>(minutesDouble);
}

bool DegreeSpinBox::parse(QString str, double *result) {
    QTextStream stream(&str);

    int degrees(0), minutes(0);
    double seconds(0);
    // %1° %2′ %3″"
    QChar symbolDegree(0), symbolMinutes(0), symbolSeconds(0);
    stream >> degrees >> symbolDegree
            >> ws >> minutes >> symbolMinutes
            >> ws >> seconds >> symbolSeconds;

    bool success = stream.status() == QTextStream::Ok
            && areSeparatorsValid(symbolDegree, symbolMinutes, symbolSeconds)
            && minutes >=0 && minutes < 60
            && seconds >=0 && seconds < 60;

    if (success && result) {
        *result = (seconds / 60.0 + minutes) / 60.0 + degrees;
    }
    return success;
}


bool DegreeSpinBox::areSeparatorsValid(QChar deg, QChar min, QChar sec) {
    return deg == QChar(L'°')
            && min == QChar(L'′')
            && sec == QChar(L'″');
}