I am trying to display a rubberband on my mapCanvas in QGIS but it seems that setToMapCanvas will only accept a QRect object. I am trying to show on the canvas the visible area of a maplayout with a rotation. I tried rotating the QRect with QTransform but I can only get the rotation to rotate from 0,0 (i.e. Top Left Corner) or a wildly random location depending on scale. Or I transform the QRect with a rotation and return it to a PolygonF only to find no way to set it to the map canvas with rubberband.

When I try to return the Polygon I get TypeError: setToMapCanvas(self, QTransform): argument 1 has unexpected type 'QPolygonF' When I try to transform the QRect I get TypeError: setToMapCanvas(self, QTransform): argument 1 has unexpected type 'transform'

mtp = self.iface.mapCanvas().mapSettings().mapToPixel()
p1 = mtp.transform(QgsPoint(rect.left(), rect.top()))
p2 = mtp.transform(QgsPoint(rect.right(), rect.bottom()))
rect = QTransform().mapToPolygon(QRect(p1.x(), p1.y(), p2.x() - p1.x(), p2.y() - p1.y()))
rect_r = rect.rotate(45)
return QPolygonF(rect_r)

When I use this code to rotate the rubberband

extent = self.mapitem.extent()
center = self.iface.mapCanvas().extent().center()
self.corner = QPointF(center.x() - 0.5 * extent.width(), center.y() - 0.5 * extent.height())
self.rect = QRectF(self.corner.x(), self.corner.y(), extent.width(), extent.height())
self.rubberband = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.PolygonGeometry)
#    tveinot 20200122 set the rubberband rotation and rotation point
self.rubberband.setTransformOriginPoint((0.5 * self.rect.width()),(0.5 * self.rect.height()))
self.rubberband.setColor(QColor(127, 127, 255, 127))

The rotation point varies depending on my scale and location. If I change (0.5 * self.rect.width()) to center.x()/y() respectively 1 degree of rotations sends the rectangle off screen.

What am I doing wrong?

  • 2
    There is no setToMapCanvas method in PyQGIS. Do you mean setToCanvasRectangle or a custom method which you've defined? And there is no setToMapCanvas method in the script above. – Kadir Şahbaz Jan 29 at 21:07
  • Yes sorry, setToCanvasRectangle is what I am using in the posted code, sorry for the description mistake. – Tyler Veinot Jan 30 at 14:49

For what it's worth, I have not been able to get the setToCanvasRectangle() method of QgsRubberBand class to work. Even when I pass it a QRect object, my code runs without error but the rubber band is not shown. I can get a good result using the setToGeometry() method though.

If I understand correctly what you are trying to do with the rubber band class, I think that the minimal snippet below should help you. This is just for testing in the console but you should be able to adapt fairly easily for a plugin.

rb = QgsRubberBand(iface.mapCanvas(),QgsWkbTypes.PolygonGeometry)
rect = iface.mapCanvas().extent() # QgsRectangle object
geom = QgsGeometry().fromRect(rect) #QgsGeometry object
# rotate geometry 30 degrees clockwise around centroid
geom.rotate(30.00, geom.centroid().asPoint())
# set rubber band to geometry

# run line below to reset (hide) the rubber band
# rb.reset()

This gives the result below.

Map canvas before running the code:

enter image description here

After running code and zooming out to see canvas extent from previous screen rotated 30 degrees around centroid and shown as a rubber band item:

enter image description here

| improve this answer | |
  • So I passed the QRect from the first part of the code as Rect to the rubberband part of the code using rb_object = QgsGeometry().fromRect(self.__canvasRect(self.rect) *Which should be the QRect return created from the earlier code" and I get the error "p1 = mtp.transform(QgsPoint(rect.left(), rect.top())) AttributeError: 'builtin_function_or_method' object has no attribute 'left'" Yet my python console says left is an attribute. It seems like the error is saying I have left as a attribute as long as I do not try to convert the result to a Geometry... – Tyler Veinot Jan 30 at 16:38
  • QgsGeometry().fromRect() method takes a QgsRectangle object not a QRect. And it looks like the first part of your code returns a QpolygonF, so I'm a bit confused about what you are doing. What is it exactly you are trying to show with the rubber band? – Ben W Jan 30 at 23:18
  • I can't help getting the impression that your current code is more complicated than it needs to be... – Ben W Jan 31 at 0:50
  • To answer your first comment, What I am trying to do in full is there is a plugin for QGIS called insta print and I use it quite a bit. I posted a feature request in 2017 for adding a rotation so you could rotate the print view and have it correlate with your chosen layout. So after taking some python courses and gaining some experience I decided to try and addd it myself, with the intention of sharing the code of course. I managed to; add the spinbox, pass the value to the layout rotation, refresh the rubberband on value change, and rotate the rubberband. Stuck on rotating it properly. – Tyler Veinot Jan 31 at 12:04
  • To your second comment, Fair enough, I completely understand. Where I am trying to add a feature to a pre-existing plugin there is some additional complication/nuances to contend with. This part is proving to be the most difficult, but it should also be the final bit. None the less I still do appreciate you taking the time to respond, it has opened up some approaches. – Tyler Veinot Jan 31 at 12:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.