Important: Please read the Qt Code of Conduct -

QRect and QRectF - contains menthod

  • Hi

    I had a quick question on a version of the contans method for QRect and QRectF

    bool QRect::contains(const QRect & rectangle, bool proper = false) const
    This is an overloaded function.
    Returns true if the given rectangle is inside this rectangle. otherwise returns false. If proper is true, this function only returns true if the rectangle is entirely inside this rectangle (not on the edge).

    bool QRectF::contains(const QRectF & rectangle) const
    This is an overloaded function.
    Returns true if the given rectangle is inside this rectangle; otherwise returns false.

    For the QRectF version, will it return true if the second rectangle is entirely in the first rectangle?
    Or on the edge?
    Or both both on the edge and inside the first rectangle?
    Are there any plans to have an overloaded version of this function that takes the proper boolean flag?


  • Moderators

    Hi, welcome to devnet.

    I don't think there will be a flag like that for the RectF class.
    It's just that it's hard(if not impossible) to define equality for floating point numbers. It would have to be defined in terms of some epsilon margin value, which would complicate interface. For example what if the two rects had different epsilons? If you need such functionality you can always define your own utility that will exactly match your needs.

  • Hi Chris

    Thanks for your response. That makes sense
    On analyzing my requirement again, I think I should be able to get away with using a qRect as opposed a qRectF

    Thanks for your help

  • Just ran into this issue as well for QRect/QRectF containing points.

    QRect r1(30, 30, 30, 30);
    QRect r2(60, 30, 30, 30);
    bool b1 = r1.contains(60, 30); // false
    bool b2 = r2.contains(60, 30); // true

    QRectF r3(30, 30, 30, 30);
    QRectF r4(60, 30, 30, 30);
    bool b3 = r3.contains(60, 30); // true
    bool b4 = r4.contains(60, 30); // true

    Intuitively this appears wrong, but the epsilon Chris mentions being used to compare the floats explains it well.

    A custom function like

    bool contains(const QRectF& rect, const QPointF& point)
    if ( rect.topLeft().x() <= point.x()
    && rect.topLeft().y() <= point.y()
    && rect.bottomRight().x() > point.x()
    && rect.bottomRight().y() > point.y())
    return true;
    return false;

    has the behavior I want, but it has assumptions and conditions that don't fit a general concept:

    • Top and left edge are considered inside (<=)
    • Bottom and right edge are considered not inside (<)
    • No epsilon so I will probably have fun with rounding errors soon

    Until then I hope it will work if I keep everything consistent.

  • Moderators

    Yeah, it comes down to the fact that practically there's no well behaved operator== or operator <= or anything that resembles equality for floating points.
    The best you can do is add third float parameter to your function and replace
    @rect.topLeft().x() <= point.x()@
    with this
    @rect.topLeft().x() < (point.x() + eps)@

    But this has another set of rounding problems so usually the answer is simple: don't bother. If you care about edges stick to fixed point math where edge has a clear representation.

Log in to reply