當前位置:編程學習大全網 - 編程語言 - 如何在Qt中使用自定義數據類型

如何在Qt中使用自定義數據類型

使用下面這個struct來做說明(這裏不管是struct還是class都壹樣):

struct Player

{

int number;

QString firstName;

QString lastName;

};

QVariant

為了能在QVariant中使用自定義數據類型做,需要使用Q_DECLARE_METATYPE()來向Qt的元系統聲明這個自定義類型。如下列所示:

struct Player

{

...

};

Q_DECLARE_METATYPE(Player);

在作為QVariant傳遞自定義數據類型時,需要使用QVariant::fromValue()或者qVariantFromValue:

Player player;

object->setProperty("property", QVariant::fromValue(player));

為了更方便壹點,妳可以在自定義類型中定義壹個QVariant() 類型轉換符:

struct Player

{

...

operator QVariant() const

{

return QVariant::fromValue(*this);

}

};

這樣我們便可以像下面這樣使用了:

Player player;

object->setProperty("property", player);

信號和槽

對於直接連接類型(默認情況下就是直接連接)而言,使用自定義數據類型做信號參數不需要做其他其他處理,就像內置數據類型壹樣:

connect(sender, SIGNAL(playerCreated(const Player&)), receiver, SLOT(addPlayer(const Player&)));

但在跨線程時如果妳還這麽做,編譯器就會給出警告了:

QObject::connect: Cannot queue arguments of type 'Player'

(Make sure 'Player' is registered using qRegisterMetaType().)

這時我們需要先註冊Player:

qRegisterMetaType<Player>("Player");?

qRegisterMetaType<Player>( );? (上面那個是錯誤的,除非名字剛好和類名壹樣)

connect(sender, SIGNAL(playerCreated(const Player&)), receiver, SLOT(addPlayer(const Player&)));

QDebug

最好是能這樣:

qDebug() << player;

而不是這樣:

qDebug() << "Player(" << player.number << "," << player.firstName << "," << player.lastName << ")";

怎麽做呢?我們需要對QDebug<<操作符重載壹下:

inline QDebug operator<<(QDebug debug, const Player& player)

{

debug.nospace() << "Player("

<< player.number << ","

<< player.firstName << ","

<< player.lastName << ")";

return debug.space();

}

QDataStream

跟上面的QDebug很像,我們也需要重載壹下<<操作符:

inline QDataStream& operator<<(QDataStream& out, const Player& player)

{

out << player.number;

out << player.firstName;

out << player.lastName;

return out;

}

inline QDataStream& operator>>(QDataStream& in, Player& player)

{

in >> player.number;

in >> player.firstName;

in >> player.lastName;

return in;

}

QSettings

QSettings 用QVariant保存鍵值,用QDataStream序列化自定義數據。(參考後面的variantToString函數) ?

為了能在QSettings中使用自定義數據類型,需要讓Qt的元系統知道有此類型,就像上面介紹QVariant部分壹樣,另外還要提供相應的QDataStream操作符,還必須註冊這個流操作符:

qRegisterMetaTypeStreamOperators<Player>("Player");

如此處理之後我們就可以像下面這樣使用了:

QSettings settings;

Player player;

settings.setValue("key", player);

QSettings settings;

Player player = value("key").value<Player>();

參考:

QString QSettingsPrivate::variantToString(const QVariant &v)

{

QString result;

switch (v.type()) {

case QVariant::Invalid:

result = QLatin1String("@Invalid()");

break;

case QVariant::ByteArray: {

QByteArray a = v.toByteArray();

result = QLatin1String("@ByteArray(");

result += QString::fromLatin1(a.constData(), a.size());

result += QLatin1Char(')');

break;

}

case QVariant::String:

case QVariant::LongLong:

case QVariant::ULongLong:

case QVariant::Int:

case QVariant::UInt:

case QVariant::Bool:

case QVariant::Double:

case QVariant::KeySequence: {

result = v.toString();

if (result.startsWith(QLatin1Char('@')))

result.prepend(QLatin1Char('@'));

break;

}

#ifndef QT_NO_GEOM_VARIANT

case QVariant::Rect: {

QRect r = qvariant_cast<QRect>(v);

result += QLatin1String("@Rect(");

result += QString::number(r.x());

result += QLatin1Char(' ');

result += QString::number(r.y());

result += QLatin1Char(' ');

result += QString::number(r.width());

result += QLatin1Char(' ');

result += QString::number(r.height());

result += QLatin1Char(')');

break;

}

case QVariant::Size: {

QSize s = qvariant_cast<QSize>(v);

result += QLatin1String("@Size(");

result += QString::number(s.width());

result += QLatin1Char(' ');

result += QString::number(s.height());

result += QLatin1Char(')');

break;

}

case QVariant::Point: {

QPoint p = qvariant_cast<QPoint>(v);

result += QLatin1String("@Point(");

result += QString::number(p.x());

result += QLatin1Char(' ');

result += QString::number(p.y());

result += QLatin1Char(')');

break;

}

#endif // !QT_NO_GEOM_VARIANT

default: {

#ifndef QT_NO_DATASTREAM

QByteArray a;

{

QDataStream s(&a, QIODevice::WriteOnly);

s.setVersion(QDataStream::Qt_4_0);

s << v;

}

result = QLatin1String("@Variant(");

result += QString::fromLatin1(a.constData(), a.size());

result += QLatin1Char(')');

#else

Q_ASSERT(!"QSettings: Cannot save custom types without QDataStream support");

#endif

break;

}

}

return result;

}

qsetting為了讓保存的ini文件能和ascii兼容,所以

我們將ini文件中的鍵值讀入到 QVariant 中,需要兩個步驟:

因為文件內的壹些字符被轉義了,比如 "\x1234\t\0"等,所以需要 unescape

從 unescape 後的字符串構造出 QVariant

當將QVariant寫入文件時:

將 QVariant 轉換成字符串

處理字符串中的特殊字符,即 escape

  • 上一篇:我想看看別人寫的作文是怎麽寫的
  • 下一篇:富士康鴻準模具是個什麽樣的企業?
  • copyright 2024編程學習大全網