Bug report #12392
QgsRubberBand not fully refreshing
Status: | Closed | ||
---|---|---|---|
Priority: | Normal | ||
Assignee: | Sandro Santilli | ||
Category: | Map Canvas | ||
Affected QGIS version: | 2.8.1 | Regression?: | No |
Operating System: | Easy fix?: | No | |
Pull Request or Patch supplied: | Yes | Resolution: | |
Crashes QGIS or corrupts data: | No | Copied to github as #: | 20566 |
Description
QgsRubberBand items sometimes not refreshing properly when another map
canvas item (QgsVertexMarker) intersects them. This happens with 2.8,
in 2.6.1 works as expected.
See: https://www.dropbox.com/s/4egl61juue9ewop/rubberband.png?dl=0 as
illustration
How to reproduce:
1. Open empty project (epsg:4326)
2. Execute this script in python console:
from PyQt4.QtCore import * from PyQt4.QtGui import * from qgis.gui import * from qgis.core import * mCursor = QgsVertexMarker(iface.mapCanvas()) mCursor.setIconType(QgsVertexMarker.ICON_BOX) mCursor.setIconSize(20) mCursor.setZValue(5) points = [[QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)]] rb = QgsRubberBand(iface.mapCanvas(), True) rb.setToGeometry(QgsGeometry.fromPolygon(points), None) rb.setColor(QColor(125, 125, 0)) rb.show() def changeCursorPos(p): mCursor.setCenter(p) iface.mapCanvas().xyCoordinates.connect(changeCursorPos)
3. Move mouse cursor over rubber band.
You can erase rubber band from bottom to some upper point.
Tested on win7 32bit
Associated revisions
Recompute rubberband extent on zoom/pan
Fix #12392
Includes testcase
Fix QgsRubberBand refresh
- Fixes invalid calculation of rubberband boundingRect
- Scales icon and pen width with rubberband when computing rect
- Recompute rubberband extent on zoom/pan
Fix #12392
Includes testcase
(backport of master commits d43d8bf 84d47c9 a844bfa)
History
#1 Updated by Anatoliy Golubev over 9 years ago
ups...code should be:
points = [ [QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)] ]
#2 Updated by Anatoliy Golubev over 9 years ago
- Assignee set to Sandro Santilli
I found that this bug was introduced in d7269595
Sandro, can you look at it?
#3 Updated by Sandro Santilli over 9 years ago
it looks like it's failing to update the lower and right sides.
Your script did not work here: TypeError: QgsGeometry.fromPolygon(unknown-type): argument 1 has unexpected type 'tuple'
Any way to reproduce this with some core tool ?
Or (even better), could you provide an automated test to include in the suite ?
#4 Updated by Anatoliy Golubev over 9 years ago
This script works fine in 2.8.1 (redmine eat double brackets)
from PyQt4.QtCore import * from PyQt4.QtGui import * from qgis.gui import * from qgis.core import * mCursor = QgsVertexMarker(iface.mapCanvas()) mCursor.setIconType(QgsVertexMarker.ICON_BOX) mCursor.setIconSize(20) mCursor.setZValue(5) points = [ [QgsPoint(0, 0), QgsPoint(20, 30), QgsPoint(0, 60)] ] rb = QgsRubberBand(iface.mapCanvas(), True) rb.setToGeometry(QgsGeometry.fromPolygon(points), None) rb.setColor(QColor(125, 125, 0)) rb.show() def changeCursorPos(p): mCursor.setCenter(p) iface.mapCanvas().xyCoordinates.connect(changeCursorPos)
#5 Updated by Sandro Santilli over 9 years ago
iface.mapCanvas().xyCoordinates.connect(changeCursorPos) File "<input>", line 4 iface.mapCanvas().xyCoordinates.connect(changeCursorPos) ^ SyntaxError: invalid syntax
#6 Updated by Anatoliy Golubev over 9 years ago
- File rubberband2.png added
I get this syntax error when there are some spaces between "mCursor.setCenter(p) and iface. iface should not be in changeCursorPos function.
You can try copy all code except last line, and then copy last line.
See attached screenshot
#7 Updated by Sandro Santilli over 9 years ago
Got it, I need to enter an additional empty line to signal end of "changeCursorPos" function (in the python console) -- trying
#8 Updated by Nyall Dawson over 9 years ago
Sandro - you probably need to override the boundingRect method in QgsRubberBand to return the correct rubber band bounds. It would seem the base implementation of this method is returning a rect which is too small for the rubber band. That would account for this behaviour...
#9 Updated by Sandro Santilli over 9 years ago
I actually wonder if QgsMapCanvasItem::boundingRect is correct, in that it assumes the bounding rectangle always starts at the upper-left corner. Reading the code it looks like "mItemSize" should be correct (it's set by QgsMapCanvasItem::setRect) but boundingRect does not take mRect in consideration at all!
#10 Updated by Sandro Santilli over 9 years ago
I've added debugging output in 2.6 and 2.8 branches to see what's going on.
First of all I noticed that even with an empty project, the QgsRubberBand::boundingRect (I added an override there, just for the sake of printing a debugging output) gets called for every pan and zoom.
Second, with the python code above, moving the rubberband around the canvas does not change the returned "boundingRect" which seems to only depend on scale. I continue to think it's always been bogus somehow...
#11 Updated by Sandro Santilli over 9 years ago
Oops, sorry, only now I realize that the "rubberband" in the test is the triangle, not the cursor. It makes sense for it to not change when moving the cursor. Looking better now :)
#12 Updated by Sandro Santilli over 9 years ago
Ok now I confirm that no matter where I pan (moving the rubberband triangle around the screen) the boundingRect (with 2.6) always reports the same value, which is only dependent on zoom/size-of-rubberband, and always starts with -1,-1.
For example
at scale 1:140,273,942:
src/gui/qgsrubberband.cpp: 522: (boundingRect) XXX rect is -1.0000000000000000,-1.0000000000000000 : 45.7176168480304597,135.0688211983073757
#13 Updated by Sandro Santilli over 9 years ago
Alright one difference is that while in 2.6 the rectangle size updates with scale, in master it seems to be fixed.
updateRect is called once at rubberband creation time in both cases. Dunno what else is supposed to change mItemSize
#14 Updated by Sandro Santilli over 9 years ago
QgsMapCanvasItem::updatePosition calls setRect again in 2.6. In master qgsrubberband overrides updatePosition to do nothing, thus the mItemSize does not change.
#15 Updated by Anatoliy Golubev over 9 years ago
QgsRubberBand::updateRect calls QgsMapCanvasItem::setRect too
// This is an hack to pass QgsMapCanvasItem::setRect what it // expects (encoding of position and size of the item) QgsPoint topLeft = m2p.toMapPoint( r.xMinimum(), r.yMinimum() ); <- double res = m2p.mapUnitsPerPixel(); QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res ); <-
Maybe thats the point? Why should we subtract r.height()*res from r.yMinimum()?
#16 Updated by Sandro Santilli over 9 years ago
updateRect call to setRect is ok, I think.
I confirm dropping the override fixes this bug. But it's to be checked what else (if anything) breaks.
I think it's better to have an automated test for this bug before fixing it. If not else if any other breackage comes out the fix for that won't re-introduce this.
Do you think you can provide an automated test for this, Anatoliy ?
#17 Updated by Anatoliy Golubev over 9 years ago
Dont know how to automate it, sorry.
#18 Updated by Sandro Santilli over 9 years ago
Theres a tests/src/gui/testqgsrubberband.cpp file you could start from
#19 Updated by Anatoliy Golubev over 9 years ago
Ok, Im look at it
#20 Updated by Sandro Santilli over 9 years ago
A fix is available here: https://github.com/qgis/QGIS/pull/1968
Adding your test there would be useful, before merging.
#21 Updated by Sandro Santilli over 9 years ago
- Target version set to Version 2.8.2
- % Done changed from 0 to 90
#22 Updated by Sandro Santilli over 9 years ago
- Pull Request or Patch supplied changed from No to Yes
#23 Updated by Sandro Santilli over 9 years ago
- Status changed from Open to Closed
Fixed in changeset a844bfa17490391bcfac54700ace76afbeac90f0.
#24 Updated by Sandro Santilli over 9 years ago
- Status changed from Closed to Reopened
reopened as the fix needs to be backported to 2.8 branch
#25 Updated by Sandro Santilli over 9 years ago
- Tag set to rotation
Also, I'd like a confirmation from the reporter about effectiveness of the fix (currently in master)
#26 Updated by Anatoliy Golubev over 9 years ago
Tested master on debian, it seems ok, refreshing works fine.
#27 Updated by Sandro Santilli over 9 years ago
- Status changed from Reopened to Closed
Fixed in changeset 37171dc0b780bae69989aced4544e51d11ceefba.