【MayaPySide】ちょっとおしゃれなUIメソッド【1日目】

QSS,Tips,StyleSheet,PySide,Tutorial,PySide2,Python,Qt,Maya

こんにちは
MayaPython Advent Calendar 2017の2日目の記事です。
全記事一覧です

【MayaPySide】ちょっとおしゃれなUIメソッド【1日目】
【MayaPySide】ちょっとおしゃれなUIメソッド【2日目】
【MayaPySide】ちょっとおしゃれなUIメソッド【3日目】

最近Twitterで角丸UIを作りたい
おしゃれなUI作りたい
なんて声がよく上がっているのでおしゃれUIの最先端(自称)の私がやってやろうじゃないか!!
ということで前半後半に分けて(予定もっと多くなるかも)作っていきましょう。
今回作るUIはこちら

かっこいい!!おしゃれ!すごい!!キャーーーーー
そんなに褒めないでくださいよー照れるじゃないですか!

はい、ということで作っていきます。

今回作るUIはフレームレスを使ったUIになります
フレームレスにするのはとても簡単なのですが問題点がいくつか出てきます
例えばマウスで移動できない
UIを閉じるボタンがないなど

ですのでマウスで移動できるように設定する、そしてUIを閉じるボタンを作る必要があります。
前半はそれらの設定とWindowを角丸にする設定をしていきます。

ということでひな型を用意します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import os
import sys

import maya.cmds as cmds
import pymel.core as pm
from maya import OpenMayaUI

from Qt.QtWidgets import *
from Qt.QtGui import *
from Qt.QtCore import *

try:
    import shiboken
except:
    import shiboken2 as shiboken

ptr = OpenMayaUI.MQtUtil.mainWindow()
parent = shiboken.wrapInstance(long(ptr), QWidget)

class Example(QMainWindow):
    def __init__(self):
        super(Example, self).__init__(parent)
        self.initUI()
        self.setButton()

    def initUI(self):
        self.setWindowOpacity(0.85)
        self.setGeometry(300, 300, 200, 150)

    def setButton(self):
        btn = QPushButton("Close", self)
        btn.move(50,50)

def Example_UI():
    global Example_UI_ex
    app = QApplication.instance()
    Example_UI_ex = Example()
    Example_UI_ex.show()
    sys.exit()
    app.exec_()

Example_UI()

実行するとCloseというボタンが一つある半透明なUIが出てくると思います
Closeと書いているのにクローズできないのでうまく消えるに設定していきます
UIをボタンで閉じるにはclose()を使います

def setButton(self):
    btn = QPushButton("Close", self)
    btn.move(50,50)
    btn.clicked.connect(self.close)

setButtonのなかに記述し、実行してみるとうまくボタンが機能しているかと思います
これでフレームレスにしても安心できます
setWindowFlagsを使用してフレームレスにしてみましょう

def initUI(self):
    self.setWindowOpacity(0.85)
    self.setGeometry(300, 300, 200, 150)
    self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)

うまくフレームレスにできました。
しかしこれだと表示した場所から移動させることができません
位置を固定するものであれば問題ないのですが
大体はそうではないのでマウスで移動するイベント処理を入れます
Exampleに入れてもいいのですが今回はクラスの継承を使って導入したいと思います

class setMainWindow(QMainWindow):
    def __init__(self):
        super(setMainWindow, self).__init__(parent)

# ~~~~~~~~~~~~~~~~~~~~~~~~
class Example(setMainWindow):
    def __init__(self):
        super(Example, self).__init__()

FramelessMainWindowというクラスを用意します。
そしてExampleの継承をFramelessMainWindowに変更します
コンストラクタはFramelessMainWindowでmayaをparentしているので空にしておきます。

mouseMoveEvent(QMouseEvent event)
mousePressEvent(QMouseEvent
event)
mouseReleaseEvent(QMouseEvent *event)

マウスで移動するイベント処理は上の3つを使用します
Exampleにイベント処理を入れます

def mouseReleaseEvent(self, pos):
    self.mc_x = pos.x()
    self.mc_y = pos.y()

def mousePressEvent(self, pos):
    self.mc_x = pos.x()
    self.mc_y = pos.y()

def mouseMoveEvent(self, pos):
    winX = pos.globalX() - self.mc_x
    winY = pos.globalY() - self.mc_y
    self.move(winX, winY)

上の処理はQMouseEventを使用しています
x(),y()でマウスのプッシュ、リリース時のマウスカーソル位置情報を取得し
globalX()とglobalY()でイベント発生時のマウスカーソルのグローバル位置情報を取得しています
あとはmove()処理でWindowを移動させるという方法です
これでマウスでwindowを移動することができました
次に角丸のUIを作っていきます
角丸のUIを作るにはsetMask()とQPalette、QPainterPathを使って作ります

def paletteUI(self):
    Palette = QPalette()
    self.setPalette(Palette)

    path = QPainterPath()
    path.addRoundedRect(self.rect(), 10, 10)
    region = QRegion(path.toFillPolygon().toPolygon())
    self.setMask(region)

QPainterPath()はPathを使って図形を作ることができるものです
図形を作り最終的にそれを使用してWindow自体をマスクし、UIを表現しています
上のコードはinitUIにself.paletteUI()と記述して読み込みます
実行すると下の画像のように変化します

せっかくなのでQLinearGradientでグラデーションを適応させてみます

def paletteUI(self):
    setColors = ['#54354e', '#6a86c7']
    Palette = QPalette()
    gradient = QLinearGradient(
        QRectF(self.rect()).topLeft(),
        QRectF(self.rect()).topRight()
    )
    gradient.setColorAt(0.0, setColors[0])
    gradient.setColorAt(1.0, setColors[1])
    Palette.setBrush(QPalette.Background, QBrush(gradient))
    self.setPalette(Palette)

    path = QPainterPath()
    path.addRoundedRect(self.rect(), 10, 10)
    region = QRegion(path.toFillPolygon().toPolygon())
    self.setMask(region)


こんな感じに色が付けれたら今回は大まかな形や設定ができましたのでここまでとします
【MayaPySide】ちょっとおしゃれなUIメソッド【2日目】の記事で細部を設定していきます


MayaPython Advent Calendar 2017の3日目の記事はhal1932さんのPython で from import を reload する。です