イメージビュアー

2016/09/03

PyQtでイメージビューワ
http://melpystudio.blog82.fc2.com/blog-entry-138.html

で、公開していただいているサンプルを自分用に改変したもの。

左ダブルクリック:画像を開く
右ダブルクリック:画像サイズを今のウィンドウに合わせる
左ドラッグ:移動
マウスホイール:拡大縮小
ステータスバーには画像上の座標

# -*- coding: utf-8 -*-

import sys,os
from PySide import QtGui,QtCore

class MainWindow(QtGui.QMainWindow):
    def __init__(self, *argv, **keywords):
        super(MainWindow,self).__init__(*argv,**keywords)
        self.view = QtGui.QGraphicsView(self)
        self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setCentralWidget(self.view)

        self.scene = ImageViewScene(self.view)
        self.view.setScene(self.scene)
        self.view.viewport().setMouseTracking(True)

        self.setGeometry(100,100,500,400)

class ImageViewScene(QtGui.QGraphicsScene):

    def __init__(self,parent):
        super(ImageViewScene, self).__init__(parent)
        self.__imageItem     = None
        self.__currentPos    = None
        self.__pressedButton = None
        self.__clickPos = None
        self.__transform = None

    def setImage(self):
        #画像を選択
        dp = os.path.expanduser('~') + '/Desktop'
        filters = "Images (*.png *.gif *.jpg)"
        fileObj = QtGui.QFileDialog.getOpenFileName(None,"File dialog", dp, filters)
        filepath = fileObj[0]
        if filepath == '':
            return
        pixmap = QtGui.QPixmap(filepath)
        self.setSceneRect(self.parent().rect())

        if self.__imageItem:
            self.removeItem(self.__imageItem)

        # 与えられたイメージをPixmapアイテムとしてシーンに追加する。-----------
        item = QtGui.QGraphicsPixmapItem(pixmap)

        # アイテムを移動可能アイテムとして設定。
        item.setFlags(QtGui.QGraphicsItem.ItemIsMovable)
        self.addItem(item)

        self.__imageItem = item
        if self.__transform:
            self.__imageItem.setTransform(self.__transform)

    def scaleRatio(self):
        #原寸大に戻す
        if not self.__transform:
            return False
        #print(self.__transform.m11(),self.__transform.m22())
        return self.__transform.m11()

    def fitImage(self):
        if not self.__imageItem:
            return

        boundingRect = self.__imageItem.boundingRect() #元の大きさ
        self.setSceneRect(self.parent().rect())
        sceneRect    = self.sceneRect()# シーンの現在の大きさ

        itemAspectRatio  = boundingRect.width() / boundingRect.height()
        sceneAspectRatio = sceneRect.width() / sceneRect.height()

        transform = QtGui.QTransform() # Transformオブジェクト

        if itemAspectRatio >= sceneAspectRatio:# 横幅に合わせる
            scaleRatio = sceneRect.width() / boundingRect.width()
        else: # 縦の高さに合わせる
            scaleRatio = sceneRect.height() / boundingRect.height()
        #拡大・縮小
        transform.scale(scaleRatio, scaleRatio)

        self.__imageItem.setTransform(transform)

        self.__transform = transform

    def mouseDoubleClickEvent(self, event):
        if event.button() == QtCore.Qt.RightButton:
            self.fitImage()
        elif event.button() == QtCore.Qt.LeftButton:
            self.setImage()

    def mousePressEvent(self, event):

        self.__currentPos    = event.scenePos()
        self.__pressedButton = event.button()

        if not self.__imageItem:
            return

        #クリックした場所の元画像での位置
        if self.__pressedButton == QtCore.Qt.LeftButton:
            localTrs = self.__imageItem.mapFromScene(event.scenePos())
            self.__clickPos = [localTrs.x(),localTrs.y()]
            print(self.__clickPos)

        #カーソルの表示
        if self.__pressedButton == QtCore.Qt.RightButton:
            cursorShape = QtCore.Qt.ClosedHandCursor
            QtGui.qApp.setOverrideCursor(QtGui.QCursor(cursorShape))

    def mouseMoveEvent(self, event):
        if not self.__imageItem:
            return

        localTrs = self.__imageItem.mapFromScene(event.scenePos())
        coor = '%d,%d' % (localTrs.x(),localTrs.y())
        self.parent().parent().statusBar().showMessage(coor)

        if not self.__currentPos:
            return

        cur = event.scenePos()
        value = cur - self.__currentPos
        transform = self.__imageItem.transform()
        if self.__pressedButton == QtCore.Qt.RightButton:
            transform *= QtGui.QTransform().translate(value.x(), value.y())

        self.__imageItem.setTransform(transform)
        self.__transform = transform
        self.__currentPos = cur

    def mouseReleaseEvent(self, event):
        self.__currentPos    = None
        self.__pressedButton = None
        QtGui.qApp.restoreOverrideCursor()

    def wheelEvent(self,event):
        # スケール処理
        if event.delta() < 0:
            value = 0.9
        else:
            value = 1.1

        # マウスカーソル位置を中心にスケールするように変換
        cur = event.scenePos()
        transform = self.__imageItem.transform()
        localTrs = self.__imageItem.mapFromScene(cur)
        transform.translate(localTrs.x(), localTrs.y()) \
            .scale(value, value) \
            .translate(-localTrs.x(), -localTrs.y())

        self.__imageItem.setTransform(transform)
        self.__transform = transform

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())