0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PySideのModel/Viewテンプレート

Posted at

maya のリグに関するツールで、複数のオブジェクトをUIに貯めておいて一括で処理を行いたいとき、リストの制御にmodel/viewアーキテクチャを使います.
リストにオブジェクトを追加したり削除したりする手順についてテンプレートを作成しました

2024-06-27_12h54_31.png

model/viewについての詳細はこちら
https://doc.qt.io/qtforpython-6/overviews/model-view-programming.html
完全に理解するのは遠い道のりなので、qiitaを始め様々なサイトの知識を頂戴しました

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

from maya import OpenMayaUI, cmds
from PySide2 import QtWidgets, QtCore, QtGui
import shiboken2

class MainUI(QtWidgets.QWidget):
    def __init__(self, parent = None):
        super(MainUI,self).__init__(parent)
        
        self.setWindowTitle('modlViewTemplate')
        self.resize(200,200)
        
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)

        self.item_list = ListWidget()
        button_refresh = QtWidgets.QPushButton('refresh')
        button_add     = QtWidgets.QPushButton('add')
        button_remove  = QtWidgets.QPushButton('remove')

        layout.addWidget(self.item_list)
        layout.addWidget(button_refresh)
        layout.addWidget(button_add)
        layout.addWidget(button_remove)

        button_refresh.clicked.connect(self.refreshItem)
        button_add.clicked.connect(self.appendItem)
        button_remove.clicked.connect(self.removeItem)

    # 選択したアイテムでリストを更新
    def refreshItem(self):
        self.item_list.listModel.clear()
        self.appendItem()

    # 選択したアイテムと既存のアイテムとの比較の差分をとって追加
    def appendItem(self):
        all_items = self.getItem()
        items = cmds.ls(sl=True)
        add_items = list(set(items)-set(all_items))
        self.item_list.listModel.addItems(add_items)

    def removeItem(self):
        sel_idx = self.item_list.listView.selectedIndexes()
        for idx in sel_idx:
            self.item_list.listModel.removeRow(idx.row())

    def getItem(self):
        all_items = []
        for i in range(self.item_list.listModel.rowCount()):
            data = self.item_list.listModel.item(i).data(0)
            all_items.append(data)
        return(all_items)

class ListView(QtWidgets.QListView):
    def __init__(self, *args, **keywords):
        super(ListView, self).__init__(*args, **keywords)
        self.setSelectionMode(QtWidgets.QListView.SingleSelection)#単独選択のみ
        self.setAlternatingRowColors(False)

class ListModel(QtGui.QStandardItemModel):
    def __init__(self,parent = None):
        super(ListModel, self).__init__(parent)

    # 複数アイテム追加のための関数
    def addItems(self, items):
        for i in items:
            item = QtGui.QStandardItem(i)
            self.appendRow(item)

class ListWidget(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super(ListWidget, self).__init__(*args, **kwargs)
        
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0,0,0,0)
        
        self.listView = ListView(self)
        layout.addWidget(self.listView)
        
        self.listModel = ListModel(self)
        self.listView.setModel(self.listModel)

def main():
    mayaWindow = shiboken2.wrapInstance(
        int(OpenMayaUI.MQtUtil.mainWindow()),QtWidgets.QWidget)
    
    existsWindow = mayaWindow.findChildren(QtWidgets.QWidget,'modelViewTmp')
    for w in existsWindow:
        w.close()
    
    ui = MainUI(mayaWindow)
    ui.setObjectName('modelViewTmp')
    ui.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)
    ui.show()

QListViewを元にListViewクラスを作成します
setSelectionModeで選択のモードを設定します.今回はオブジェクトを削除するときに複数を一度に処理する方法ではないので、単独選択のみになっています.

class ListView(QtWidgets.QListView):
    def __init__(self, *args, **keywords):
        super(ListView, self).__init__(*args, **keywords)
        self.setSelectionMode(QtWidgets.QListView.SingleSelection)#単独選択のみ
        self.setAlternatingRowColors(False)

QStandardItemModelを元にListModelクラスを作成します
複数アイテムを渡して追加する関数を付け加えています
mayaで取得したアイテムをQStandardItemに変換してappendRowで追加します

class ListModel(QtGui.QStandardItemModel):
    def __init__(self,parent = None):
        super(ListModel, self).__init__(parent)

    # 複数アイテム追加のための関数
    def addItems(self, items):
        for i in items:
            item = QtGui.QStandardItem(i)
            self.appendRow(item)

UIに追加するためにQwidgetを元にしたオブジェクトにListVewを組み込んで、ListModelをsetします

class ListWidget(QtWidgets.QWidget):
    def __init__(self, *args, **kwargs):
        super(ListWidget, self).__init__(*args, **kwargs)
        
        layout = QtWidgets.QVBoxLayout(self)
        layout.setContentsMargins(0,0,0,0)
        
        self.listView = ListView(self)
        layout.addWidget(self.listView)
        
        self.listModel = ListModel(self)
        self.listView.setModel(self.listModel)

リスト内容の操作のための関数
refresh
clear関数でモデルの内容をクリアした後、後述のappendItem関数でアイテムを追加します

def refreshItem(self):
    self.item_list.listModel.clear()
    self.appendItem()

appendItem
後述のgetItem関数でリスト内のすべてのアイテムを取得、選択していオブイジェクトとの差分をsetの比較で抽出した後ListModelに追加したaddItems関数を用いてモデルに追加します

def appendItem(self):
    all_items = self.getItem()
    items = cmds.ls(sl=True)
    add_items = list(set(items)-set(all_items))
    self.item_list.listModel.addItems(add_items)

removeItem
リストで選択されているモデルデータから行番号を取得してアイテムを削除します

def removeItem(self):
    sel_idx = self.item_list.listView.selectedIndexes()
    for idx in sel_idx:
        self.item_list.listModel.removeRow(idx.row())

getItem
リストの行数を取得後、各行のモデルデータのデータ内容をfor文で配列に追加して戻り値としてすべてのデータの文字の配列を返します

    all_items = []
    for i in range(self.item_list.listModel.rowCount()):
        data = self.item_list.listModel.item(i).data(0)
        all_items.append(data)
    return(all_items)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?