QT5.15.2 中的qspinbox64

问题描述 投票:0回答:2

我尝试按照

中的建议创建一个 qspinbox64

QT 中的 64 位 int Spin Box

qspinbox64.h

#define QSPINBOX64_H

#include <QtGui>
#include <QtWidgets>


namespace Ui {
class QSpinBox64;
}

class QSpinBox64Private;
class Q_WIDGETS_EXPORT QSpinBox64 : public QAbstractSpinBox//QSpinBox
{
    Q_OBJECT
    Q_PROPERTY(int64_t minimum READ minimum WRITE setMinimum)
    Q_PROPERTY(int64_t maximum READ maximum WRITE setMaximum)

    Q_PROPERTY(int64_t value READ value WRITE setValue NOTIFY valueChanged USER true)

    int64_t m_minimum;
    int64_t m_maximum;
    int64_t m_value;
public:
    explicit QSpinBox64(QWidget *parent = nullptr)
    {
       connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
    }

    ~QSpinBox64()
    {

    }
    int64_t value() const
    {
        return m_value;
    }
    int64_t minimum() const
    {
        return m_minimum;
    }
    int64_t maximum() const
    {
        return m_maximum;
    }
    void setMinimum(int64_t min)
    {
        m_minimum = min;
    }
    void setMaximum(int64_t max)
    {
        m_maximum = max;
    }
    void setRange(int64_t min, int64_t max)
    {
        setMinimum(min);
        setMaximum(max);
    }
    virtual void stepBy(int steps)
    {
        auto new_value = m_value;
        if (steps < 0 && new_value + steps > new_value) {
            new_value = std::numeric_limits<qlonglong>::min();
        }
        else if (steps > 0 && new_value + steps < new_value) {
            new_value = std::numeric_limits<qlonglong>::max();
        }
        else {
            new_value += steps;
        }

        lineEdit()->setText(textFromValue(new_value));
        setValue(new_value);
    }

protected:
    virtual QValidator::State validate(QString &text, int &pos) const
    {
        //return validator->validate(text, pos);
        bool ok;
        int64_t val = text.toLongLong(&ok);
        if (!ok)
            return QValidator::Invalid;

        if (val < m_minimum || val > m_maximum)
            return QValidator::Invalid;

        return QValidator::Acceptable;
    }
    virtual int64_t valueFromText(const QString &text) const
    {
        bool ok;
        return text.toLongLong(&ok, 10);
    }
    virtual QString textFromValue(int64_t value) const
    {
        return QString::number(value, 10).toUpper();
    }
    virtual QAbstractSpinBox::StepEnabled stepEnabled() const;

public
    Q_SLOTS:
    void setValue(int64_t val)
    {
        if (m_value != val) {
            lineEdit()->setText(textFromValue(val));
            m_value = val;
        }
    }
    void onEditFinished()
    {
            QString input = lineEdit()->text();
            int pos = 0;
            if (QValidator::Acceptable == validate(input, pos))
                setValue(valueFromText(input));
            else
                lineEdit()->setText(textFromValue(m_value));
        }
Q_SIGNALS:
    void valueChanged(int64_t v);


private:
    Ui::QSpinBox64 *ui;

    Q_DISABLE_COPY(QSpinBox64)

    Q_DECLARE_PRIVATE(QSpinBox64)
};

#endif 

主.cpp

#include <QHBoxLayout>

#include "qspinbox64.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QSpinBox64 spinBox;
    spinBox.setWindowTitle(QObject::tr("QSpinBox64"));
    spinBox.show();
    return app.exec();
}

编译后出现错误:

G:\proj\build-qspinbox64-Desktop_Qt_5_15_2_MSVC2019_64bit-Debug\debug\moc_qspinbox64.cpp:141: 
error: C2491: 'QSpinBox64::staticMetaObject': definition of dllimport static data member not allowed

我应该怎样做才能避免这个错误?

c++ qt5
2个回答
0
投票

罪魁祸首是

Q_WIDGETS_EXPORT
,定义于
qtwidgetsglobal.h

#  if defined(QT_BUILD_WIDGETS_LIB)
#    define Q_WIDGETS_EXPORT Q_DECL_EXPORT
#  else
#    define Q_WIDGETS_EXPORT Q_DECL_IMPORT
#  endif

您应该通过将此行添加到 .pro 文件来在项目中声明

QT_BUILD_WIDGETS_LIB

DEFINES += QT_BUILD_WIDGETS_LIB

一些旁注:

  1. 你缺少头球护卫
    #ifndef QSPINBOX64_H
  2. 构造函数应调用基类构造函数并按照原始帖子中的说明设置最小值/最大值。
  3. stepEnabled()
    需要实施

explicit QSpinBox64(QWidget *parent = nullptr) : QAbstractSpinBox{parent}
{
    setMaximum(std::numeric_limits<int64_t>::max());
    setMinimum(std::numeric_limits<int64_t>::min());
    connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
}

virtual QAbstractSpinBox::StepEnabled stepEnabled() const
{
    return QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
}

0
投票

我真的不喜欢链接的原始代码,因为它的工作原理与

QSpinBox
类 plus 不能处理
stepBy
函数中设置的最小值/最大值一样。

这是我的方法,无需弄乱所有这些 Qt 宏:

#pragma once
#include <QAbstractSpinBox>
#include <QLineEdit>
#include <QString>
#include <QValidator>
#include <QWidget>
#include <limits>

class LongLongSpinBox : public QAbstractSpinBox
{
    Q_OBJECT

    using type = long long;

    type m_minimum;
    type m_maximum;
    type m_value;

    public:
    explicit LongLongSpinBox(QWidget* parent = nullptr) : QAbstractSpinBox(parent)
    {
        setRange(std::numeric_limits<type>::min(), std::numeric_limits<type>::max());
        QObject::connect(lineEdit(), &QLineEdit::textEdited, this, &LongLongSpinBox::onEditFinished);
    };
    ~LongLongSpinBox(){};

    type value() const
    {
        return m_value;
    };

    type minimum() const
    {
        return m_minimum;
    };

    void setMinimum(type min)
    {
        m_minimum = min;
    }

    type maximum() const
    {
        return m_maximum;
    };

    void setMaximum(type max)
    {
        m_maximum = max;
    }

    void setRange(type min, type max)
    {
        setMinimum(min);
        setMaximum(max);
    }

    void stepBy(int steps) override
    {
        type new_value;

        if (steps > 0 && m_value > std::numeric_limits<type>::max() - steps) // overflow
            new_value = m_maximum;
        else if (steps < 0 && m_value < std::numeric_limits<type>::min() - steps) // underflow
            new_value = m_minimum;
        else if ((m_value + steps) < m_minimum)
            new_value = m_minimum;
        else if ((m_value + steps) > m_maximum)
            new_value = m_maximum;
        else
            new_value = m_value + steps;

        setValue(new_value);
    }

    protected:
    // bool event(QEvent *event);
    QValidator::State validate(QString& input, int&) const override
    {
        if (input.isEmpty())
            return QValidator::Acceptable;

        // technically should check if the range allows positive / negative values
        if (input.length() == 1 && (input[0] == '+' || input[0] == '-'))
            return QValidator::Acceptable;

        bool ok;
        type val = input.toLongLong(&ok);
        if (!ok)
            return QValidator::Invalid;

        if (val < m_minimum || val > m_maximum)
            return QValidator::Invalid;

        return QValidator::Acceptable;
    }

    virtual type valueFromText(const QString& text) const
    {
        return text.toLongLong();
    }

    virtual QString textFromValue(type val) const
    {
        return QString::number(val);
    }
    // virtual void fixup(QString &str) const;

    virtual QAbstractSpinBox::StepEnabled stepEnabled() const
    {
        return StepUpEnabled | StepDownEnabled;
    }

    public Q_SLOTS:
    void setValue(type val)
    {
        if (m_value != val)
        {
            auto new_text = textFromValue(val);
            lineEdit()->setText(new_text);
            m_value = val;
            emit valueChanged(val);
            emit valueChanged(new_text);
        }
    }

    void onEditFinished()
    {
        auto new_text = text();
        m_value = valueFromText(new_text);
        emit valueChanged(m_value);
        emit valueChanged(new_text);
    }

    Q_SIGNALS:
    void valueChanged(type v);
    void valueChanged(const QString& v);
};
© www.soinside.com 2019 - 2024. All rights reserved.