【Maya × PySide2】フォルダ内画像を←→キーで切り替えられるビューアを作ってみた



Mayaを使った制作現場で「資料画像をサッと確認したいな」と思う場面、多くないですか？

- チートシートを確認したい
- 三面図をパラパラ見たい
- 設定資料や参考画像をすぐ見たい

そんなとき、いちいち画像ビューアを立ち上げたり、ファイルを探したりするのは面倒……！

ということで今回は、**PySide2で「フォルダ内の画像を←→キーで切り替えて表示できるビューア」を作ってみました。**

---

## 🧩 できること

- 指定したフォルダ内の画像をすべて読み込み
- ← → キーで前後に切り替え
- Escキーで閉じる
- 画像は画面いっぱいに拡大表示（半透明）
- ミニランチャーからワンクリックで起動

用途は自由自在。チートシート、設定資料、三面図、絵コンテ、表情資料……全部これでOK！

---

## 🛠 使用技術

- Maya 2023
- PySide2（Maya標準搭載）
- Python 3.x（Maya同梱）

---

## 💻 実装のポイント

### 1. PySide2でGUI構築

MayaではPySide2を使って、QtベースのUIが組めます。
今回は `QDialog` + `QLabel` を使って、画像を表示できるビューアを作成しました。

### 2. フォルダ内の画像を一括取得

```python
os.listdir(folder)
```
でファイル一覧を取得し、拡張子が `.jpg`, `.png`, `.bmp` などのものだけを抽出。
これで好きなだけ画像を放り込めます。

### 3. キー入力で切り替え

`keyPressEvent()` をオーバーライドして、← → Esc キーに処理を割り当てています。
直感的に操作できます。

### 4. ミニランチャーで呼び出し

デザインも少しだけかわいく、ふわっとした水色UIに。
「画像ビューアを開く」ボタンからいつでもアクセスできます。

---

## ✨ こんなふうに使ってます

- キャラクターの三面図を切り替えて確認
- チートシートを手元で確認

---

## 🔚 おわりに


今後はアイデアを思いつき次第、改善していく予定です。

---

## ✅ コード全文はこちら

```python
import os
from PySide2 import QtWidgets, QtGui, QtCore
import maya.OpenMayaUI as omui
from shiboken2 import wrapInstance

def get_maya_main_window():
    ptr = omui.MQtUtil.mainWindow()
    return wrapInstance(int(ptr), QtWidgets.QMainWindow)

class ImageViewer(QtWidgets.QDialog):
    def __init__(self, folder_path, parent=get_maya_main_window()):
        super(ImageViewer, self).__init__(parent)
        self.setWindowTitle("画像ビューア")
        self.setWindowFlags(QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint)
        self.setWindowOpacity(0.9)
        self.setWindowModality(QtCore.Qt.NonModal)
        self.setFocusPolicy(QtCore.Qt.StrongFocus)

        self.image_paths = self.load_images_from_folder(folder_path)
        if not self.image_paths:
            QtWidgets.QMessageBox.warning(self, "画像なし", "指定フォルダに画像がありません。")
            self.close()
            return

        self.index = 0
        self.screen = QtWidgets.QApplication.primaryScreen().geometry()
        self.setGeometry(self.screen)

        self.layout = QtWidgets.QVBoxLayout()
        self.setLayout(self.layout)

        self.label = QtWidgets.QLabel(self)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.layout.addWidget(self.label)

        self.update_image()

        close_btn = QtWidgets.QPushButton("閉じる", self)
        close_btn.setFixedSize(100, 30)
        close_btn.move(20, 20)
        close_btn.clicked.connect(self.close)
        close_btn.setStyleSheet("""
            QPushButton {
                background-color: #4dd0e1;
                border: none;
                border-radius: 10px;
                padding: 6px 12px;
                font-size: 13px;
                color: white;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #26c6da;
            }
        """)

    def load_images_from_folder(self, folder):
        exts = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
        images = [os.path.join(folder, f) for f in sorted(os.listdir(folder))
                  if os.path.splitext(f)[1].lower() in exts]
        return images

    def update_image(self):
        pixmap = QtGui.QPixmap(self.image_paths[self.index])
        scaled = pixmap.scaled(self.screen.width(), self.screen.height(), QtCore.Qt.KeepAspectRatio)
        self.label.setPixmap(scaled)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Right:
            self.index = (self.index + 1) % len(self.image_paths)
            self.update_image()
        elif event.key() == QtCore.Qt.Key_Left:
            self.index = (self.index - 1) % len(self.image_paths)
            self.update_image()
        elif event.key() == QtCore.Qt.Key_Escape:
            self.close()

class MiniLauncher(QtWidgets.QDialog):
    def __init__(self, parent=get_maya_main_window()):
        super(MiniLauncher, self).__init__(parent)
        self.setWindowTitle("画像ビューア ランチャー")
        self.setWindowFlags(QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint)
        self.setFixedSize(200, 100)
        self.move(50, 200)

        self.setStyleSheet("""
            QDialog {
                background-color: qlineargradient(
                    spread:pad, x1:0, y1:0, x2:1, y2:1,
                    stop:0 #d6f2fb, stop:1 #b3e5fc);
                border: 2px solid #a2d4ec;
                border-radius: 15px;
            }
            QPushButton {
                background-color: #4dd0e1;
                border: none;
                border-radius: 12px;
                padding: 8px 14px;
                font-size: 14px;
                color: white;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #26c6da;
            }
        """)

        btn = QtWidgets.QPushButton("画像ビューアを開く", self)
        btn.clicked.connect(self.open_viewer)
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.addWidget(btn)

    def open_viewer(self):
        folder_path = r"C:\\Users\\micoa\\OneDrive\\デスクトップ\\maya\\viewer_images"
        self.viewer = ImageViewer(folder_path)
        self.viewer.show()

try:
    mini_launcher.close()
except:
    pass

mini_launcher = MiniLauncher()
mini_launcher.show()
```

---

## 🙌 最後に

「こんなの欲しかった！」と思ってくれた方、ぜひ試してみてください。