Qt 教程二(二)
4. QVariant
QVariant(变体数据类型)这个类很神奇,或者说方便。很多时候,需要几种不同的数据类型需要传递,如果用结构体,又不大方便,容器保存的也只是一种数据类型,而QVariant则可以统统搞定。
QVariant 这个类型充当着最常见的数据类型的联合。QVariant 可以保存很多Qt的数据类型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且还有C++基本类型,如int、float等。
4.1 标准类型
将标准类型转换为QVariant类型
// 这类转换需要使用QVariant类的构造函数, 由于比较多, 大家可自行查阅Qt帮助文档, 在这里简单写几个 QVariant(int val); QVariant(bool val); QVariant(double val); QVariant(const char *val); QVariant(const QByteArray &val); QVariant(const QString &val); ...... // 使用设置函数也可以将支持的类型的数据设置到QVariant对象中 // 这里的 T 类型, 就是QVariant支持的类型 void setValue(const T &value); // 该函数行为和 setValue() 函数完全相同 [static] QVariant fromValue(const T &value);
Exmple
QVariant v(5); QVariant v; v.setValue(5); QVariant v = QVariant::fromValue(5); int i = v.toInt(); // i is now 5 QString s = v.toString(); // s is now "5"
判断 QVariant中封装的实际数据类型
Type 是枚举类型
//获取类型,返回的是一个枚举类型;如QVariant::Int ... Type type() const; //获取类型名 const char *typeName() const; //根据类型id(枚举)获取类型名(字符串) [static] const char *typeToName(int typeId); //根据类型名(字符串)获取类型id(枚举) [static] Type nameToType(const char *name);
将QVariant对象转换为实际的数据类型
//在转换之前可以先判断能够转换成对应的类型 bool canConvert(int targetTypeId) const bool canConvert() const bool toBool() const; QByteArray toByteArray() const; double toDouble(bool *ok = Q_NULLPTR) const; float toFloat(bool *ok = Q_NULLPTR) const; int toInt(bool *ok = Q_NULLPTR) const; QString toString() const; ...... T value() const //v.value<int>();
4.2 自定义类型
除了标准类型, 我们自定义的类型也可以使用QVariant类进行封装, 被QVariant存储的数据类型需要有一个默认的构造函数和一个拷贝构造函数。为了实现这个功能,首先必须使用Q_DECLARE_METATYPE()宏。通常会将这个宏放在类的声明所在头文件的下面, 原型为:
Q_DECLARE_METATYPE(Type)
使用的具体步骤如下:
第一步: 定义类型,并注册
//自定义类型 class Animal { public: Animal(){} //必须要有默认构造函数 //拷贝构造函数也必须有,不过没有深、浅拷贝时,用默认的即可 Animal(QString name):_name(name){} void show() { qDebug()<<"Animal show name is :"<< _name <<endl; } private: QString _name; }; //自定义类型注册 Q_DECLARE_METATYPE(Animal);
第二步: 使用forvalue()存储对象
int main() { //QVariant vt(Animal("snake")); //不可以通过构造函数存自定义类型 QVariant vt; //有以下两种方法可以,存自定义类型 vt = QVariant::fromValue(Animal("dog")); //① vt.setValue(Animal("cat")); //② //如果能转换到Animal类型,就转换 if(vt.canConvert<Animal>()) { Animal animal = vt.value<Animal>(); animal.show(); } return 0; }
操作涉及的API如下:
// 如果当前QVariant对象可用转换为对应的模板类型 T, 返回true, 否则返回false bool canConvert() const; // 将当前QVariant对象转换为实际的 T 类型 T value() const;
5. 位置和尺寸
在QT中我们常见的 点, 线, 尺寸, 矩形 都被进行了封装, 下边依次为大家介绍相关的类。
5.1 QPoint
QPoint类封装了我们常用用到的坐标点 (x, y), 常用的 API如下:
void QPoint::setX(int x); void QPoint::setY(int y); int QPoint::x() const; int &QPoint::rx(); int QPoint::y() const; int &QPoint::ry(); //如果x和y坐标都为0则返回true,否则返回false bool isNull() const //返回x()和y()的绝对值之和,传统上称为从原点到该点的向量的“曼哈顿长度”。 //(p1-p2).manhattanLength(); int manhattanLength() const //返回一个交换了x和y坐标的点: QPoint{1, 2}.transposed() // {2, 1} QPoint transposed() const // 直接通过坐标对象进行算术运算: 加减乘除 QPoint &QPoint::operator*=(float factor); QPoint &QPoint::operator*=(double factor); QPoint &QPoint::operator*=(int factor); QPoint &QPoint::operator+=(const QPoint &point); QPoint &QPoint::operator-=(const QPoint &point); QPoint &QPoint::operator/=(qreal divisor); ...
5.2 QLine
QLine是一个直线类, 封装了两个坐标点 (两点确定一条直线)
常用API如下:
// 设置直线的起点坐标 void setP1(const QPoint &p1); // 设置直线的终点坐标 void setP2(const QPoint &p2); void setPoints(const QPoint &p1, const QPoint &p2); void setLine(int x1, int y1, int x2, int y2); QPoint p1() const; // 返回直线的起始点坐标 QPoint p2() const; // 返回直线的终点坐标 QPoint center() const; // 返回值直线的中心点坐标, (p1() + p2()) / 2 int x1() const; // 返回值直线起点的 x 坐标 int y1() const; // 返回值直线起点的 y 坐标 int x2() const; // 返回值直线终点的 x 坐标 int y2() const; // 返回值直线终点的 y 坐标 int dx() const //返回直线向量的水平分量 int dy() const //返回直线向量的垂直分量 // 用给定的坐标点平移这条直线 void translate(const QPoint &offset); void translate(int dx, int dy); // 用给定的坐标点平移这条直线, 返回平移之后的坐标点(不会改变这条线的坐标) QLine translated(const QPoint &offset) const; QLine translated(int dx, int dy) const; // 直线对象进行比较 bool operator!=(const QLine &line) const; bool operator==(const QLine &line) const;
5.3 QSize
在QT中QSize类用来形容长度和宽度, 常用的API如下:
void setWidth(int width) void setHeight(int height); int width() const; // 得到宽度 int &rwidth(); // 得到宽度的引用 int height() const; // 得到高度 int &rheight(); // 得到高度的引用 void transpose(); // 交换高度和宽度的值 QSize transposed() const; // 交换高度和宽度的值, 返回交换之后的尺寸信息 //返回一个大小,宽为当前大小与other的最小值,高为当前大小与other的最小值 QSize boundedTo(const QSize& oterSize) //返回一个大小,宽为当前大小与other的最大值,高为当前大小与other的最大值 QSize expandedTo(const QSize &otherSize) const /* 根据指定的模式,按给定的宽度和高度缩放矩形: 如果mode为Qt::IgnoreAspectRatio,则大小设置为(width, height)。 如果mode为Qt::KeepAspectRatio,当前大小将在内部缩放到一个尽可能大的矩形(宽度,高度),保持高宽比。 如果mode是Qt::KeepAspectRatioByExpanding,当前大小被缩放到一个矩形,尽可能小的外部(宽度,高度),保持长宽比。 */ void scale(int width, int height, Qt::AspectRatioMode mode) void scale(const QSize &size, Qt::AspectRatioMode mode) QSize scaled(int width, int height, Qt::AspectRatioMode mode) const QSize scaled(const QSize &s, Qt::AspectRatioMode mode) const // 进行算法运算: 加减乘除 QSize &operator*=(qreal factor); QSize &operator+=(const QSize &size); QSize &operator-=(const QSize &size); QSize &operator/=(qreal divisor);
5.4 QRect
在Qt中使用 QRect类来描述一个矩形, 常用的API如下:
// 构造一个空对象 QRect::QRect(); // 基于左上角坐标, 和右下角坐标构造一个矩形对象 QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight); // 基于左上角坐标, 和 宽度, 高度构造一个矩形对象 QRect::QRect(const QPoint &topLeft, const QSize &size); // 通过 左上角坐标(x, y), 和 矩形尺寸(width, height) 构造一个矩形对象 QRect::QRect(int x, int y, int width, int height); // 设置矩形的尺寸信息, 左上角坐标不变 void QRect::setSize(const QSize &size); // 设置矩形左上角坐标为(x,y), 大小为(width, height) void QRect::setRect(int x, int y, int width, int height); // 设置矩形宽度 void QRect::setWidth(int width); // 设置矩形高度 void QRect::setHeight(int height); // 返回值矩形左上角坐标 QPoint QRect::topLeft() const; // 返回矩形右上角坐标 // 该坐标点值为: QPoint(left() + width() -1, top()) QPoint QRect::topRight() const; // 返回矩形左下角坐标 // 该坐标点值为: QPoint(left(), top() + height() - 1) QPoint QRect::bottomLeft() const; // 返回矩形右下角坐标 // 该坐标点值为: QPoint(left() + width() -1, top() + height() - 1) QPoint QRect::bottomRight() const; // 返回矩形中心点坐标 QPoint QRect::center() const; // 返回矩形上边缘y轴坐标 int QRect::top() const; int QRect::y() const; // 返回值矩形下边缘y轴坐标 int QRect::bottom() const; // 返回矩形左边缘 x轴坐标 int QRect::x() const; int QRect::left() const; // 返回矩形右边缘x轴坐标 int QRect::right() const; // 返回矩形的高度 int QRect::width() const; // 返回矩形的宽度 int QRect::height() const; // 返回矩形的尺寸信息 QSize QRect::size() const; //调整矩形的尺寸 (左上角和右下角坐标偏移量) void QRect::adjust(int dx1, int dy1, int dx2, int dy2) QRect QRect::adjusted(int dx1, int dy1, int dx2, int dy2) const
QPoint,QLine,QSize,QRect各自都还有浮点型版本的,分别是QPointF,QLineF,QSizeF,QRectF,函数基本一样
6. 日期和时间
6.1. QDate
// 构造函数 QDate::QDate(); QDate::QDate(int y, int m, int d); // 公共成员函数 // 重新设置日期对象中的日期 bool QDate::setDate(int year, int month, int day); // 给日期对象添加 ndays 天 QDate QDate::addDays(qint64 ndays) const; // 给日期对象添加 nmonths 月 QDate QDate::addMonths(int nmonths) const; // 给日期对象添加 nyears 月 QDate QDate::addYears(int nyears) const; // 得到日期对象中的年/月/日 int QDate::year() const; int QDate::month() const; int QDate::day() const; void QDate::getDate(int *year, int *month, int *day) const; /*日期对象格式化 d - 没有前导零的日子 (1 to 31) dd - 前导为0的日子 (01 to 31) ddd - 显示(缩写) 周一、周二、周三、周四、周五、周六、周日 dddd - 显示(完整) 星期一、星期二、星期三、星期四、星期五、星期六、星期日 M - 没有前导零的月份(1到12) MM - 前导零的月份(01到12) MMM - 缩写 1月、2月、3月... MMMM - 完整 一月、二月、三月... yy - 两个数字的年 (00 to 99) yyyy - 以四位数表示的年份 */ QString QDate::toString(const QString &format) const; // 操作符重载 ==> 日期比较 bool QDate::operator!=(const QDate &d) const; bool QDate::operator<(const QDate &d) const; bool QDate::operator<=(const QDate &d) const; bool QDate::operator==(const QDate &d) const; bool QDate::operator>(const QDate &d) const; bool QDate::operator>=(const QDate &d) const; // 静态函数 -> 得到本地的当前日期 [static] QDate QDate::currentDate();
6.2. QTime
// 构造函数 QTime::QTime(); /* h ==> must be in the range 0 to 23 m and s ==> must be in the range 0 to 59 ms ==> must be in the range 0 to 999 */ QTime::QTime(int h, int m, int s = 0, int ms = 0); // 公共成员函数 // Returns true if the set time is valid; otherwise returns false. bool QTime::setHMS(int h, int m, int s, int ms = 0); QTime QTime::addSecs(int s) const; QTime QTime::addMSecs(int ms) const; // 示例代码 QTime n(14, 0, 0); // n == 14:00:00 QTime t; t = n.addSecs(70); // t == 14:01:10 t = n.addSecs(-70); // t == 13:58:50 t = n.addSecs(10 * 60 * 60 + 5); // t == 00:00:05 t = n.addSecs(-15 * 60 * 60); // t == 23:00:00 // 从时间对象中取出 时/分/秒/毫秒 // Returns the hour part (0 to 23) of the time. Returns -1 if the time is invalid. int QTime::hour() const; // Returns the minute part (0 to 59) of the time. Returns -1 if the time is invalid. int QTime::minute() const; // Returns the second part (0 to 59) of the time. Returns -1 if the time is invalid. int QTime::second() const; // Returns the millisecond part (0 to 999) of the time. Returns -1 if the time is invalid. int QTime::msec() const; // 时间格式化 /* -- 时 h ==> The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) hh ==> The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) H ==> The hour without a leading zero (0 to 23, even with AM/PM display) HH ==> The hour with a leading zero (00 to 23, even with AM/PM display) -- 分 m ==> The minute without a leading zero (0 to 59) mm ==> The minute with a leading zero (00 to 59) -- 秒 s ==> The whole second, without any leading zero (0 to 59) ss ==> The whole second, with a leading zero where applicable (00 to 59) -- 毫秒 zzz ==> The fractional part of the second, to millisecond precision, including trailing zeroes where applicable (000 to 999). -- 上午或者下午 AP or A ==> 使用AM/PM(大写) 描述上下午, 中文系统显示汉字 ap or a ==> 使用am/pm(小写) 描述上下午, 中文系统显示汉字 */ QString QTime::toString(const QString &format) const; // 操作符重载 ==> 时间比较 bool QTime::operator!=(const QTime &t) const; bool QTime::operator<(const QTime &t) const; bool QTime::operator<=(const QTime &t) const; bool QTime::operator==(const QTime &t) const; bool QTime::operator>(const QTime &t) const; bool QTime::operator>=(const QTime &t) const; // 静态函数 -> 得到当前时间 [static] QTime QTime::currentTime();
经时计时器
QTime的经时计时器已经过时了,推荐使用QElapsedTimer。
//QTime已废弃的函数 // 开始计时 void QTime::start(); // 计时结束 int QTime::elapsed() const; // 重新计时 int QTime::restart(); // 推荐使用的API函数 // QElapsedTimer 类 void QElapsedTimer::start(); qint64 QElapsedTimer::restart(); qint64 QElapsedTimer::elapsed() const;
主要的使用方法就是测量一个操作耗时多久,例子如下:
QElapsedTimer elapse; elapse.start(); for(int i = 0;i<10000000;i++); qDebug()<<elapse.elapsed()<<endl;
6.3. QDateTime
// 构造函数 QDateTime::QDateTime(); QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec = Qt::LocalTime); // 公共成员函数 // 设置日期 void QDateTime::setDate(const QDate &date); // 设置时间 void QDateTime::setTime(const QTime &time); // 给当前日期对象追加 年/月/日/秒/毫秒, 参数可以是负数 QDateTime QDateTime::addYears(int nyears) const; QDateTime QDateTime::addMonths(int nmonths) const; QDateTime QDateTime::addDays(qint64 ndays) const; QDateTime QDateTime::addSecs(qint64 s) const; QDateTime QDateTime::addMSecs(qint64 msecs) const; // 得到对象中的日期 QDate QDateTime::date() const; // 得到对象中的时间 QTime QDateTime::time() const; // 日期和时间格式, 格式字符参考QDate 和 QTime 类的 toString() 函数 QString QDateTime::toString(const QString &format) const; // 操作符重载 ==> 日期时间对象的比较 bool QDateTime::operator!=(const QDateTime &other) const; bool QDateTime::operator<(const QDateTime &other) const; bool QDateTime::operator<=(const QDateTime &other) const; bool QDateTime::operator==(const QDateTime &other) const; bool QDateTime::operator>(const QDateTime &other) const; bool QDateTime::operator>=(const QDateTime &other) const; // 静态函数 // 得到当前时区的日期和时间(本地设置的时区对应的日期和时间) [static] QDateTime QDateTime::currentDateTime();