class Magnifier(QtGui.QGraphicsPixmapItem): def __init__(self, main, parent=None, img=None, graphic=None, scene=None, police=None, texte=None): super(Magnifier, self).__init__(parent, scene) self.main = main d = dict(shape="square", width=0, height=0, img=img, police=police, texte=texte, graphic=graphic, scene=scene, pix=None, cur_pos=None, old_X=None, old_Y=None) for key, value in d.items(): setattr(self, key, value) self.setFlags(QtGui.QGraphicsItem.ItemIsMovable | QtGui.QGraphicsItem.ItemIsFocusable) self.setAcceptHoverEvents(True) self._moved = Moved() # Create signals # Signals are class defined at the end of this script # http://docs.python.org/howto/descriptor.html def positionChanged(): def fget(self): return self._moved.positionChanged return locals() positionChanged = property(**positionChanged()) def set_size(self, width, height): self.width = self.montexte.size().width() self.height = self.montexte.size().height() def setup(self): """setup the magnifier. """ self.cur_pos = self.__get_center() self.setPos(self.cur_pos[2], self.cur_pos[3]) self.__create_magnifier() if not self.old_X: self.recenter_magnifying_glass() self.old_X, self.old_Y = self.pos().x(), self.pos().y() def __create_magnifier(self): """Call functions to build the magnifying glass. """ self.__set_sttext() self.orig = self.__get_orig_center() self.__set_square() def __set_sttext(self): mat = QTransform() self.montexte = QStaticText(self.texte) self.montexte.prepare(mat, self.police) self.set_size(self.montexte.size().width(), self.montexte.size().height()) return self.montexte def __set_square(self): self.txt = self.__set_sttext() rect = QtCore.QRect(0, 0, self.width, self.height) color = QtGui.QColor() color.setRgb(0, 0, 0, 0) self.pix = QtGui.QPixmap(QtCore.QSize(self.width + 2, self.height + 2)) self.pix.fill(color) painter = QtGui.QPainter() painter.begin(self.pix) painter.setFont(self.police) painter.drawStaticText(0, 0, self.montexte) painter.end() self.setPixmap(self.pix) return self.pix def __update(self, x, y): """Update the original coordinates when the magnifying glass is moved. """ self.orig[2] += x self.orig[3] += y def move_by(self, x, y): self.moveBy(x, y) self.__update(x, y) def __get_center(self): """Return the center of the scene. This assume both scene and image have the same geometry. Returns: list[center X, center Y, top left x, top left Y] """ cX, cY = int(self.scene.width() / 2), int(self.scene.height() / 2) posX, posY = cX - int(self.width / 2), cY - int(self.height / 2) return [cX, cY, posX, posY] def get_pos(self): """Return position of magnifying glass. Returns: QPointF(float, float) """ return self.pos() def set_pos(self, pos): """Move magnifying glass to pos. Keyword arguments: pos -- QPointF """ if isinstance(pos, QtCore.QPointF): X, Y = pos.x(), pos.y() else: X, Y = pos[0], pos[1] cur = self.pos() m_X, m_Y = X - self.pos().x(), Y - self.pos().y() self.moveBy(m_X, m_Y) self.__update(m_X, m_Y) self.positionChanged.emit([cur.x(), cur.y(), X, Y]) def __get_orig_center(self): """Return the original position at the creation of the magnifier. Returns : list -- center of pixmap magnified and corner top left. """ cX, cY = int(self.graphic.width() / 2), int(self.graphic.height() / 2) posX, posY = cX - int(self.width / 2), cY - int(self.height / 2) return [cX, cY, posX, posY] def recenter_magnifying_glass(self): """Move the magnifying glass from center image to center graphicsView. """ timer = QtCore.QTimeLine(1000); timer.setFrameRange(0, 50) self.animation = QtGui.QGraphicsItemAnimation() self.animation.setItem(self); self.animation.setTimeLine(timer) c = self.width / 2.0 dest = self.graphic.mapToScene(self.graphic.width() / 2 - c, self.graphic.height() / 2 - c) deltaX = dest.x() - self.pos().x() deltaY = dest.y() - self.pos().y() j, k, l, m = deltaX / 50, deltaY / 50, self.pos().x(), self.pos().y() for i in range (50): l, m = l + j, m + k self.animation.setPosAt(i / 50.0, QtCore.QPointF(l, m)) self.__update(j, k) timer.start() #-------------------------------- # Events #-------------------------------- def mousePressEvent(self, event, auto=0): # auto = 0 if event is caused by self # auto = 1 if event is given by other, i.e. event filter of main if auto: pos = self.graphic.mapToScene(event.pos()) else: pos = event.scenePos() if event.button() == 1: self.old_X, self.old_Y = pos.x(), pos.y() event.accept() else: event.ignore() def mouseMoveEvent(self, event, auto=0): # auto = 0 if event is caused by self # auto = 1 if event is given by other, i.e. event filter of main if auto: pos = self.graphic.mapToScene(event.pos()) else: pos = event.scenePos() if event.button() == 2: return cur = self.pos() X, Y = pos.x(), pos.y() m_X, m_Y = X - self.old_X, Y - self.old_Y self.old_X, self.old_Y = X, Y self.moveBy(m_X, m_Y) self.__update(m_X, m_Y) event.accept() def hoverEnterEvent(self, event): shape = QtGui.QPixmap("resources/cross_cursor_32.png") cursor = QtGui.QCursor(shape, -1, -1) self.setCursor(cursor) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.quit() elif event.key() == 16777234: # arrow LEFT self.move_by(-5, 0) self.positionChanged.emit([self.pos().x() + 5, self.pos().y(), self.pos().x(), self.pos().y()]) elif event.key() == 16777235: # arrow UP self.move_by(0, -5) self.positionChanged.emit([self.pos().x(), self.pos().y() + 5, self.pos().x(), self.pos().y()]) elif event.key() == 16777236: # arrow RIGHT self.move_by(5, 0) self.positionChanged.emit([self.pos().x() - 5, self.pos().y(), self.pos().x(), self.pos().y()]) elif event.key() == 16777237: # arrow DOWN self.move_by(0, 5) self.positionChanged.emit([self.pos().x(), self.pos().y() - 5, self.pos().x(), self.pos().y()]) elif event.key() == 83: # Key S used for enable / disable shadow effect try: self.main.shadow.setEnabled(not self.main.shadow.isEnabled()) except: pass