何时使用Qt图形浮点类?

何时使用Qt图形浮点类?,qt,Qt,Qt有一组图形类,有两种变体:整数精度和浮点精度 这些是我能记得的 | QLine | QLineF | | QMargins | QMarginsF | | QPoint | QPointF | | QRect | QRectF | | QSize | QSizeF | 除了明显的区别,一个使用整数,另一个使用浮点数,正如他们的名字和官方文件中所说的那样,我有相当多的疑问 一个类家族和另一个类家族的用例是什么 位置和大小是否大于其整数对应项 分数

Qt有一组图形类,有两种变体:整数精度和浮点精度
这些是我能记得的

|    QLine | QLineF    |
| QMargins | QMarginsF |
|   QPoint | QPointF   |
|    QRect | QRectF    |
|    QSize | QSizeF    |
除了明显的区别,一个使用整数,另一个使用浮点数,正如他们的名字和官方文件中所说的那样,我有相当多的疑问

  • 一个类家族和另一个类家族的用例是什么
  • 位置和大小是否大于其整数对应项
  • 分数值
  • 画画的时候有什么不同吗
  • 如果使用QLineF而不是QLine,绘图是否更平滑

虽然这些类通常是可互换的,并且具有几乎相同的实现,但它们在用法和结果上存在着特殊的差异

基于整数的类主要用于屏幕坐标(小部件位置、大小等),通常基于像素单位(显然是整数)考虑

但是,在处理定位/碰撞和绘图时,存在着重要的差异

考虑以下几点:

>>> p = QtCore.QPoint(1, 1)
>>> r = QtCore.QRect(0, 0, 1, 1)
>>> print(r.contains(p))
False
>>> r = QtCore.QRectF(0, 0, 1, 1)
>>> print(r.contains(p))
True
这是因为QRect只考虑整数(“像素”)大小,显然
(1,1)
位于“另一个像素”上

QRect对于和函数也是特殊的,因为(如文档中所述)由于历史原因,它们总是返回
left+width-1
top+height-1

>>> r = QtCore.QRect(0, 0, 1, 1)
>>> print(r.right())
0
有鉴于此,请始终记住,这些坐标的设置器(包括
set*
move*
)也同样适用:

浮点类还具有基于整数的类所不具备的功能(主要是因为实现它们是不可能的/有用的/合理的)。
例如,QLineF类:

  • 可以返回与另一个QLineF(或其扩展的交点)的交点
  • 具有获取和设置直线自身角度(从其
    p1
    起点)或与另一条直线创建的角度(或者,更好的是,如果它们不相交,则其延伸)的函数[1]
  • 可以从极轴创建,给定长度和角度
浮点类允许更精确的绘图和定位,当您需要抗锯齿绘制或处理可缩放或基于比例值的内容时(考虑放大的Qgraphicscene或文本显示,因为字体是基于矢量的)。
例如,以下内容将给出非常不同的结果:

painter.setRenderHints(painter.Antialiasing)
painter.drawRect(QtCore.QRect(1, 1, 2, 2))
painter.drawRect(QtCore.QRectF(1, 1, 2.5, 2.5))
<> P> >重要的是记住,所有接受数值作为主要参数的Q画师的简单绘图函数总是使用整数值(我相信这是由于Python的动态类型,因为C++函数只接受有符号整数):

最后,虽然Qt(和Python)有时允许两种类型的透明使用,但通常严格要求使用其中一种:

  • 所有与几何图形相关的小部件函数只接受整数类(
    setGeometry(QRect)
    resize(QSize)
    ,等等)
  • 对于必须返回几何值的函数重写也是如此,例如
    sizeHint()
    、项模型的
    SizeHintRole
    、由QStyle子类返回的矩形或为QStyleOption设置的矩形
  • QRegion只能接受QPolygon和QRect,因为它是一个像素映射对象
  • QGraphicsRecItem、QGraphicsSellipseItem和QGraphicsPolygonItem仅允许其构造函数或setter中的浮点类
  • 复杂构造函数使用其精度类型的类(QRect不接受QPointF或QSizeF等)
  • 所有映射QGraphicsCENE坐标的函数在映射到场景时必须使用整数类,从场景映射时必须使用浮点类
当您需要从一种类型转换为另一种类型时,只需使用浮点类的构造函数或它提供的
to[*]
函数即可:

intRect = QtCore.QRect(0, 0, 10, 10)
floatRect = QtCore.QRectF(intRect)
newIntRect = floatRect.toRect()
intTopLeft = floatRect.topLeft().toPoint()
intSize = floatRect.size().toSize()
midRadiusLine = QtCore.QLineF.fromPolar(
    intRect.width() * .5, 45).translated(floatRect.center())
intMidRadiusLine = midRadius.toLine()

[1] 请注意,设置0-360范围之外的角度可能会产生意外结果:
line.setAngle(361)
将导致
line.angle()
等于0.999999999748,这是由于浮点“[im]精度”和Pi的性质。

是的,可以使用fp值在亚像素边界上定位对象。确定,这有点道理,但Qt文档在这方面有点欠缺。
painter.drawRect(0.5, 0.5, 5.5, 5.5)
# same as:
painter.drawRect(0, 0, 5, 5)
# so you should use:
painter.drawRect(QtCore.QRectF(0.5, 0.5, 5.5, 5.5))
intRect = QtCore.QRect(0, 0, 10, 10)
floatRect = QtCore.QRectF(intRect)
newIntRect = floatRect.toRect()
intTopLeft = floatRect.topLeft().toPoint()
intSize = floatRect.size().toSize()
midRadiusLine = QtCore.QLineF.fromPolar(
    intRect.width() * .5, 45).translated(floatRect.center())
intMidRadiusLine = midRadius.toLine()