3

I'm trying to write a simple application that rotates a png image when a button is pressed. I have it all working fine except that as the image rotates it deviates from it's centre in a south-east direction. I would have thought it wasn't rotating around its centre, but it returns to the origin every 45 degrees of rotation, which is strange.

On a key event I'm simply calling:

pixmap = pixmap.transformed(QtGui.QTransform().rotate(-self.rot), QtCore.Qt.SmoothTransformation)

Is there a way to set the origin of the transformation to stop the image moving around?

Jean-Sébastien
  • 2,649
  • 1
  • 16
  • 21
user1971541
  • 31
  • 1
  • 2

1 Answers1

6

A simple solution, if you are using a QLabel to draw the QPixmap, is to set the alignment of the QLabel to AlignCenter. Moreover, to avoid an initial resizing of the QLabel during the first 45 degrees of the image rotation, the minimum size of the QLabel can be set to the value of the pixmap's diagonal. The image should then properly rotate around its centre without any unwanted back-and-forth translation.

Below I demonstrate how this can be done in a simple application:

import sys
from PyQt4 import QtGui, QtCore
import urllib

class myApplication(QtGui.QWidget):
    def __init__(self, parent=None):
        super(myApplication, self).__init__(parent)

        #---- Prepare a Pixmap ----

        url = ('http://sstatic.net/stackexchange/img/logos/' +
               'careers/careers-icon.png?v=0288ba302bf6')
        self.img = QtGui.QImage()
        self.img.loadFromData(urllib.urlopen(url).read())

        pixmap = QtGui.QPixmap(self.img)

        #---- Embed Pixmap in a QLabel ----

        diag = (pixmap.width()**2 + pixmap.height()**2)**0.5

        self.label = QtGui.QLabel()
        self.label.setMinimumSize(diag, diag)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setPixmap(pixmap)

        #---- Prepare a Layout ----

        grid = QtGui.QGridLayout()

        button = QtGui.QPushButton('Rotate 15 degrees')
        button.clicked.connect(self.rotate_pixmap)

        grid.addWidget(self.label, 0, 0)
        grid.addWidget(button, 1, 0)

        self.setLayout(grid)

        self.rotation = 0

    def rotate_pixmap(self):

        #---- rotate ----

        # Rotate from initial image to avoid cumulative deformation from
        # transformation

        pixmap = QtGui.QPixmap(self.img)
        self.rotation += 15

        transform = QtGui.QTransform().rotate(self.rotation)
        pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)

        #---- update label ----

        self.label.setPixmap(pixmap)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    instance = myApplication()  
    instance.show()    

    sys.exit(app.exec_())

Which results in:

enter image description here

Alternatively, this post : can't get the image to rotate in center in Qt, seems to address your issue if you are painting the QPixmap directly with QPainter.

Community
  • 1
  • 1
Jean-Sébastien
  • 2,649
  • 1
  • 16
  • 21
  • 1
    The fixed-size is a red herring, because in your example the window would simply resize to accomodate the image. The only relevant variable is the alignment. I suspect that the OP is using a label with its alignment set to `AlignTop | AlignLeft` (or perhaps just the default `AlignCenter | AlignLeft`), since that would account for the image appearing to move towards the south-east and back again as it's rotated. – ekhumoro Aug 10 '15 at 14:43
  • Thanks for your comment @ekhumoro. I've rephrased my answer to take into account your comment. I've also changed the `setFixedSize` to `setMinimumSize` in the example. – Jean-Sébastien Aug 10 '15 at 15:16