(1)本章开始学习 QT 里的绘图事件 QPaint。绘图涉及了画笔 QPen 与 QBrush。但绘图最终也涉及坐标系,与点,线,矩形这些基础的经典的图形定义。 所以,先来学习一下 QT 里如何为一个坐标系中的点定义一个类 , QPoint 与 QPointF。 本类的继承关系如下 :

(2)源码显示, 本类是支持流运算操作符的 :

(3) 不给这个全局模板友元函数举例,因为总是报错,我也不知道为什么,不可理解 :

++以及 :

(4)本类的源代码,都直接给出了 QT 自己的实现,就不再举例了,也因为时间紧迫。本类还是很容易根据源码进行理解的。举例的意义不大。重点还是画图, QPaint。 本 QPoint 类的源代码定义于 qpoint . h :
#ifndef QPOINT_H
#define QPOINT_H
#include <QtCore/qnamespace.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGPoint;
#endif
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT QDataStream & operator<< (QDataStream &, const QPoint & );
Q_CORE_EXPORT QDataStream & operator>> (QDataStream &, QPoint & );
Q_CORE_EXPORT QDebug operator<< (QDebug , const QPoint & );
Q_CORE_EXPORT size_t qHash(QPoint key, size_t seed = 0) noexcept;
/*
The QPoint class defines a point in the plane using integer precision.
Note: All functions in this class are reentrant.
Detailed Description :
一个点由x坐标和y坐标指定,这些坐标可以通过x()和y()函数来访问。
如果x和y都被设置为0,则isNull()函数将返回true。
这些坐标可以通过setX()和setY()函数来设置(或修改),
或者通过rx()和ry()函数来设置,这些函数返回坐标的引用(从而允许直接操作)。
给定一个点p,以下陈述都是等价的:
QPoint p;
p.setX(p.x() + 1);
p += QPoint(1, 0);
p.rx()++; //可见,引用更方便
QPoint对象也可以用作向量:加法和减法定义与向量相同(每个分量分别相加).
QPoint对象也可以被整数或qreal除或乘。
此外,QPoint类提供了manhattanLength()函数, //曼哈顿距离
该函数提供了一个廉价的近似值,用于表示QPoint对象作为向量的长度。
最后,QPoint对象既可以被流式传输,也可以被比较。
*/
class QPoint
{
private:
friend class QTransform;
int xp;
int yp;
/*
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Test
template <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Test
using type = _Ty;
};
template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
*/
template <std::size_t I, typename P, //这里期待 P 是 QPoint 相关的类型
std::enable_if_t<(I < 2), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<P>, QPoint>, bool> = true>
friend constexpr decltype(auto) get(P && p) noexcept //这里为本类定义了一个友元全局模板函数
{ //不用在模板参数里给出 P,因为可以从函数形参里得到。
if constexpr (I == 0)
return (std::forward<P>(p).xp);
else if constexpr (I == 1)
return (std::forward<P>(p).yp);
}
public:
constexpr QPoint() noexcept : xp(0), yp(0) {}
constexpr QPoint(int xpos, int ypos) noexcept : xp(xpos), yp(ypos) {}
constexpr inline bool isNull() const noexcept { return xp == 0 && yp == 0; }
constexpr inline int x() const noexcept { return xp; }
constexpr inline int y() const noexcept { return yp; }
constexpr inline int & rx() noexcept { return xp; }
constexpr inline int & ry() noexcept { return yp; }
constexpr inline void setX(int x) noexcept { xp = xpos; }
constexpr inline void setY(int y) noexcept { yp = ypos; }
constexpr inline int manhattanLength() const { return qAbs(x()) + qAbs(y()); }
//注意,曼哈顿距离是坐标的 x + y,而不是 x^2 + y^2
constexpr QPoint transposed() const noexcept { return {yp, xp}; } //坐标转置
constexpr static inline int dotProduct(const QPoint & p1, const QPoint & p2)
{ return p1.xp * p2.xp + p1.yp * p2.yp; } //矢量乘法
constexpr inline QPoint & operator+=(const QPoint & p )
{ xp += p.xp;
yp += p.yp;
return * this;
}
constexpr inline QPoint & operator-=(const QPoint & p )
{ xp -= p.xp;
yp -= p.yp;
return * this;
}
constexpr inline QPoint & operator*=( float factor)
{ xp = qRound(xp * factor);
yp = qRound(yp * factor);
return * this;
}
constexpr inline QPoint & operator*=( double factor)
{ xp = qRound(xp * factor);
yp = qRound(yp * factor);
return * this;
}
constexpr inline QPoint & operator*=( int factor)
{ xp = xp * factor;
yp = yp * factor;
return * this;
}
constexpr inline QPoint & operator/=( qreal divisor)
{ xp = qRound(xp / divisor);
yp = qRound(yp / divisor);
return * this;
}
//*************************************************************************
//****************以下是关于本类的全局友元符号运算符函数*************************
//*************************************************************************
friend constexpr inline //点的相等比较
bool operator== (const QPoint & p1, const QPoint & p2) noexcept
{ return p1.xp == p2.xp && p1.yp == p2.yp; }
friend constexpr inline //点的不等比较
bool operator!= (const QPoint & p1, const QPoint & p2) noexcept
{ return p1.xp != p2.xp || p1.yp != p2.yp; }
friend constexpr inline //点的坐标相加
QPoint operator+ (const QPoint & p1, const QPoint & p2) noexcept
{ return QPoint(p1.xp + p2.xp, p1.yp + p2.yp); }
friend constexpr inline //点的坐标相减
QPoint operator- (const QPoint & p1, const QPoint & p2) noexcept
{ return QPoint(p1.xp - p2.xp, p1.yp - p2.yp); }
friend constexpr inline //点的线性乘法
QPoint operator* (const QPoint & p , float factor)
{ return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
friend constexpr inline //点的线性乘法
QPoint operator* (const QPoint & p, double factor)
{ return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
friend constexpr inline //点的线性乘法
QPoint operator* (const QPoint & p, int factor) noexcept
{ return QPoint(p.xp * factor, p.yp * factor); }
friend constexpr inline //点的线性乘法
QPoint operator* ( float factor, const QPoint & p)
{ return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
friend constexpr inline //点的线性乘法
QPoint operator* ( double factor, const QPoint & p)
{ return QPoint(qRound(p.xp * factor), qRound(p.yp * factor)); }
friend constexpr inline //点的线性乘法
QPoint operator* ( int factor, const QPoint & p) noexcept
{ return QPoint(p.xp * factor, p.yp * factor); }
friend constexpr inline //点的线性除法
QPoint operator/ (const QPoint & p, qreal c)
{ return QPoint(qRound(p.xp / c), qRound(p.yp / c)); }
friend constexpr inline //这不是加法, 这是正号, +8
QPoint operator+ (const QPoint & p) noexcept { return p; }
friend constexpr inline //这不是减法, 这是负号, -8
QPoint operator- (const QPoint & p) noexcept
{ return QPoint(-p.xp, -p.yp); }
}; // 完结 class QPoint
Q_DECLARE_TYPEINFO(QPoint, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
/*****************************************************************************
QPoint/QPointF tuple protocol
*****************************************************************************/
namespace std
{
template <>
class tuple_size<QT_PREPEND_NAMESPACE(QPoint)>
: public integral_constant<size_t, 2> {};
template <>
class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)>
{ public: using type = int; };
template <>
class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)>
{ public: using type = int; };
template <>
class tuple_size<QT_PREPEND_NAMESPACE(QPointF)>
: public integral_constant<size_t, 2> {};
template <>
class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)>
{ public: using type = QT_PREPEND_NAMESPACE(qreal); };
template <>
class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)>
{ public: using type = QT_PREPEND_NAMESPACE(qreal); };
}
#endif // QPOINT_H
(5) 给出浮点 QPointF 的源码,不再如同 QPoint 那样详细整理了 :
size_t qHash(QPointF, size_t seed = 0) = delete;
//QPointF stream functions
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPointF &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPointF &);
Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p);
class QPointF
{
private:
friend class QTransform;
qreal xp;
qreal yp;
template <std::size_t I,
typename P,
std::enable_if_t<(I < 2), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<P>, QPointF>, bool> = true>
friend constexpr decltype(auto) get(P &&p) noexcept
{
if constexpr (I == 0)
return (std::forward<P>(p).xp);
else if constexpr (I == 1)
return (std::forward<P>(p).yp);
}
public:
constexpr QPointF() noexcept;
constexpr QPointF(const QPoint & p) noexcept;
constexpr QPointF(qreal xpos, qreal ypos) noexcept;
inline bool isNull() const noexcept;
constexpr inline qreal x() const noexcept;
constexpr inline qreal y() const noexcept;
constexpr inline qreal & rx() noexcept;
constexpr inline qreal & ry() noexcept;
constexpr inline void setX(qreal x) noexcept;
constexpr inline void setY(qreal y) noexcept;
constexpr inline qreal manhattanLength() const;
constexpr QPointF transposed() const noexcept { return {yp, xp}; }
constexpr QPoint toPoint() const;
constexpr inline QPointF & operator+=(const QPointF & p); //也有这些复合运算符成员函数
constexpr inline QPointF & operator-=(const QPointF & p);
constexpr inline QPointF & operator*=( qreal c);
constexpr inline QPointF & operator/=( qreal c);
constexpr static inline qreal dotProduct(const QPointF & p1, const QPointF & p2)
{
return p1.xp * p2.xp + p1.yp * p2.yp;
}
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
friend constexpr inline bool operator==(const QPointF & p1, const QPointF & p2)
{
return ((!p1.xp || !p2.xp)
? qFuzzyIsNull(p1.xp - p2.xp)
: qFuzzyCompare(p1.xp, p2.xp)) && (
(!p1.yp || !p2.yp)
? qFuzzyIsNull(p1.yp - p2.yp)
: qFuzzyCompare(p1.yp, p2.yp)
);
}
friend constexpr inline bool operator!=(const QPointF & p1, const QPointF & p2)
{
return !(p1 == p2);
}
QT_WARNING_POP
friend constexpr inline QPointF operator+(const QPointF & p1, const QPointF & p2)
{ return QPointF(p1.xp + p2.xp, p1.yp + p2.yp); }
friend constexpr inline QPointF operator-(const QPointF & p1, const QPointF & p2)
{ return QPointF(p1.xp - p2.xp, p1.yp - p2.yp); }
friend constexpr inline QPointF operator*(const QPointF & p , qreal c)
{ return QPointF(p.xp * c, p.yp * c); }
friend constexpr inline QPointF operator*(qreal c, const QPointF & p)
{ return QPointF(p.xp * c, p.yp * c); }
friend constexpr inline QPointF operator/(const QPointF & p , qreal divisor)
{
Q_ASSERT(divisor < 0 || divisor > 0);
return QPointF(p.xp / divisor, p.yp / divisor);
}
friend constexpr inline QPointF operator+(const QPointF & p) { return p; }
friend constexpr inline QPointF operator-(const QPointF & p)
{ return QPointF(-p.xp, -p.yp); }
}; //完结 class QPointF
Q_DECLARE_TYPEINFO(QPointF, Q_PRIMITIVE_TYPE);
/*****************************************************************************
QPointF inline functions
*****************************************************************************/
constexpr inline QPointF::QPointF() noexcept : xp(0), yp(0) { }
constexpr inline QPointF::QPointF(qreal xpos, qreal ypos) noexcept : xp(xpos), yp(ypos) { }
constexpr inline QPointF::QPointF(const QPoint &p) noexcept : xp(p.x()), yp(p.y()) { }
constexpr inline qreal QPointF::manhattanLength() const
{
return qAbs(x()) + qAbs(y());
}
inline bool QPointF::isNull() const noexcept
{
return qIsNull(xp) && qIsNull(yp);
}
constexpr inline qreal QPointF::x() const noexcept
{
return xp;
}
constexpr inline qreal QPointF::y() const noexcept
{
return yp;
}
constexpr inline void QPointF::setX(qreal xpos) noexcept
{
xp = xpos;
}
constexpr inline void QPointF::setY(qreal ypos) noexcept
{
yp = ypos;
}
constexpr inline qreal &QPointF::rx() noexcept
{
return xp;
}
constexpr inline qreal &QPointF::ry() noexcept
{
return yp;
}
constexpr inline QPointF &QPointF::operator+=(const QPointF &p)
{
xp += p.xp;
yp += p.yp;
return *this;
}
constexpr inline QPointF &QPointF::operator-=(const QPointF &p)
{
xp -= p.xp;
yp -= p.yp;
return *this;
}
constexpr inline QPointF &QPointF::operator*=(qreal c)
{
xp *= c;
yp *= c;
return *this;
}
constexpr inline QPointF &QPointF::operator/=(qreal divisor)
{
Q_ASSERT(divisor > 0 || divisor < 0);
xp /= divisor;
yp /= divisor;
return *this;
}
constexpr inline QPoint QPointF::toPoint() const
{
return QPoint(qRound(xp), qRound(yp));
}
(6)
谢谢
1345

被折叠的 条评论
为什么被折叠?



