株式会社デジタル・フロンティア-Digital Frontier

Header

Main

  • TOP
  • DF TALK
  • PySideでUIオブジェクトをアニメーションさせてみる

PySideでUIオブジェクトをアニメーションさせてみる

2016/5/16

Tag: ,

お久しぶりです。4月よりTD室から開発室へ異動して来ました田辺です。
どうぞ宜しくお願い致します。

今回やる内容についてですが、題名の通り

「PySideでUIオブジェクトをアニメーションさせてみる」

です。

以前、PySideを使用して作成されたすごく凝ったUIのツールを見せて頂きまして
デザイン面もそうですが、何よりUIのアニメーションが上手く取り入れられていて、
PySideでもこのような面白いUIも作れるものなのかと驚いたのを今でも覚えています。

業務でツールを作っている中では、そこまでUIばかりに時間を割くことも出来ませんし
この機会に基礎的な部分を試してみたので紹介させて頂きます。

では、早速やっていきます。

簡単にUIを作成

ベースのGUIにボタン1つのシンプルなUIを作ります。

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

import sys
from PySide import QtCore
from PySide import QtGui


class GUI(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        self.setWindowTitle("Animation Test")
        # ベースのGUIサイズを600×400に設定
        self.resize(600, 400)

        button = QtGui.QPushButton("Animation Button", self)

        # ボタンを配置する位置座標とサイズの指定: x, y, w, h
        button.setGeometry(QtCore.QRect(0, 100, 100, 50))


def main():
    app = QtGui.QApplication(sys.argv)
    gui = GUI()
    gui.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

上記のスクリプトを実行すると、ベースのGUI内にAnimation Buttonというボタンが表示されます。

buttonにアニメーションを設定する際に座標を指定する必要があるため、layout を使用せずに
setGeometory でサイズと配置する座標を設定しています。

ボタンの移動アニメーションを作成

ボタンを押したら、ボタンを横方向に移動するアニメーションを作成してみます。

アニメーションを作成するにあたって QPropertyAnimation というものを使用しています。

下記のコードを追加して、実行してみてください。

class GUI(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)

        self.setWindowTitle("Animation Test")
        # ベースのGUIサイズを600×400に設定
        self.resize(600, 400)

        button = QtGui.QPushButton("Animation Button", self)

        # ボタンを配置する位置座標とサイズの指定: x, y, w, h
        button.setGeometry(QtCore.QRect(0, 100, 100, 50))

        # buttonの移動アニメーションを作成
        move_anim = self.create_move_anim(button)

        def start_move_anim():
            move_anim.start()

        # buttonをクリックしたら、移動アニメーション開始
        button.clicked.connect(start_move_anim)

    def create_move_anim(self, button):
        """ Buttonに対して行う移動アニメーションを作成
        """
        # buttonのposプロパティをアニメーション化
        animation = QtCore.QPropertyAnimation(button, "pos")

        # アニメーションする時間の長さを設定(msec)
        animation.setDuration(1000)

        # setDurationで設定した時間をかけて、指定した場所に移動
        animation.setEndValue(QtCore.QPoint(button.x() + 400, button.y()))

        return animation

Animation Buttonをクリックするとボタンが右の方へ移動したでしょうか。

■説明

animation = QtCore.QPropertyAnimation(button, "pos")

QPropertyAnimationを使用して、buttonに対してposプロパティを変化させるための
アニメーションオブジェクトを作成します。

# アニメーションする時間の長さを設定(msec)
animation.setDuration(1000)

# setDurationで設定した時間をかけて、指定した場所に移動
animation.setEndValue(QtCore.QPoint(button.x() + 400, button.y()))

animationオブジェクトに対して、setDurationでアニメーションにかける時間と
setEndValueで終了時に到達する場所を指定します。

move_anim.start()

startでアニメーションを開始というのが処理の流れです。

変化させるプロパティの部分をbuttonが持っている size など別のプロパティに変更することによって
ボタンのサイズを変更するアニメーションも作ることも出来ます。

アニメーションの仕方を変更

QEasingCurveを使用することでアニメーションの仕方を変更することが出来ます。

PySideのリファレンスサイトに飛んで頂き

PySide.QtCore.QEasingCurve.Type

の項目を見ていただくと分かりますが種類が沢山あります。

今回はその中から InOutBack というものに変更してみます。

下記のコードを追加して、実行してみて下さい。

# buttonの移動アニメーションを作成
move_anim = self.create_move_anim(button)

# アニメーションの種類を InOutBack に変更
move_anim.setEasingCurve(QtCore.QEasingCurve.InOutBack)

def start_move_anim():
    move_anim.start()

ボタンをクリックした際のアニメーションの仕方が変更されたでしょうか。
InOutBackの部分を変更することで、別のものにも変更出来るので試して頂ければと思います。

移動アニメーションと同時にサイズ変更アニメーションを行う

移動とサイズ変更の2つのプロパティを同時に変化させてみたいと思います。

アニメーションの作成に関しては、前述の通りですが複数のアニメーションを設定するためには、
AnimationGroupというものを使用します。

下記の通りにコメントアウトとコードの追加をして、実行してみてください。

        # # buttonの移動アニメーションを作成
        # move_anim = self.create_move_anim(button)

        # # アニメーションの種類を InOutBack に変更
        # move_anim.setEasingCurve(QtCore.QEasingCurve.InOutBack)

        # def start_move_anim():
        #     move_anim.start()

        # # buttonをクリックしたら、移動アニメーション開始
        # button.clicked.connect(start_move_anim)

        # 移動とサイズ変更を同時に行うアニメーションを作成
        par_anim = self.create_parallel_animation(button)

        def start_par_anim():
            par_anim.start()

        # buttonをクリックしたら、アニメーション開始
        button.clicked.connect(start_par_anim)

    def create_size_change_animation(self, button):
        """ Buttonに対してい行うサイズ変更アニメーションを作成
        """
        # buttonのgeometryプロパティをアニメーション化
        animation = QtCore.QPropertyAnimation(button, "size")

        # アニメーションする時間の長さ(msec)
        animation.setDuration(1000)

        # setDurationで設定した時間までに最終的に変化させるプロパティを設定
        animation.setEndValue(QtCore.QSize(button.width() + 100,
                                           button.height() + 100))
        return animation

    def create_parallel_animation(self, button):
        """ Buttonを移動すると同時にサイズを変更するアニメーションを作成
        """
        # アニメーションを同時に実行するためのアニメーショングループを作成
        animation_group = QtCore.QParallelAnimationGroup()

        # 移動アニメーションを作成
        move_anim = self.create_move_anim(button)
        # サイズ変更アニメーションを作成
        size_change_anim = self.create_size_change_animation(button)

        # アニメーショングループに作成したアニメーションを登録
        animation_group.addAnimation(move_anim)
        animation_group.addAnimation(size_change_anim)

        return animation_group

ボタンを押した際に移動アニメーションと同時にサイズ変更アニメーションが実行されたでしょうか。

■説明

2つのアニメーションを同時に行うためには、
QParallelAnimationGroup というものを使って複数のアニメーションを登録することで
start時に登録されているアニメーションを同時に実行することが出来ます。

ちなみに移動とサイズ変更のプロパティを同時に変化させる場合であれば、
geometryプロパティを変化させることでも実現可能です。

移動アニメーションとサイズ変更アニメーションを順番に行う

アニメーションを順番に実行するためには、また別のAnimationGroupを使うことで実現できます。

下記の通りにコメントアウトとコードの追加をして、実行してみてください。

        # # 移動とサイズ変更を同時に行うアニメーションを作成
        # par_anim = self.create_parallel_animation(button)

        # def start_par_anim():
        #     par_anim.start()

        # # buttonをクリックしたら、アニメーション開始
        # button.clicked.connect(start_par_anim)

        # 移動とサイズ変更を順番に行うアニメーションを作成
        seq_anim = self.create_sequential_animation(button)

        def start_seq_anim():
            seq_anim.start()

        # buttonをクリックしたら、アニメーション開始
        button.clicked.connect(start_seq_anim)

    def create_sequential_animation(self, button):
        """ Buttonを移動後にサイズを変更するアニメーションを作成
        """
        # アニメーションを順番に実行するためのアニメーショングループを作成
        animation_group = QtCore.QSequentialAnimationGroup()

        # 移動アニメーションを作成
        move_anim = self.create_move_anim(button)
        # サイズ変更アニメーションを作成
        size_change_anim = self.create_size_change_animation(button)

        # 移動アニメーションを登録
        animation_group.addAnimation(move_anim)
        # 移動アニメーションとサイズ変更アニメーションの間の待ち時間を設定 (msec)
        animation_group.addPause(500)
        # サイズ変更アニメーションを登録
        animation_group.addAnimation(size_change_anim)

        return animation_group

ボタンをクリックすると移動し、停止後にサイズが大きくなるアニメーションが実行されたでしょうか。

■説明

順番にアニメーションを実行するためには、
QSequentialAnimationGroup というものを使用することで実現出来ます。
使用方法は、QParallelAnimationGroup の時と同じでインスタンス化したオブジェクトに対して
addAnimationでアニメーションを登録することで登録した順番にアニメーションが実行されます。
また、addPauseでアニメーションとアニメーションの間の待ち時間を設定出来ます。

まとめ

ここまで読んで頂き、ありがとうございました。
今回は、PySideでのUIのアニメーションについて紹介させて頂きました。
回転やフェードイン/フェードアウトなどのアニメーションも出来るかと思ったのですが、
残念ながらUIオブジェクトで行う方法は見つけることが出来ませんでした。
また、設定は複雑になりますが高度なアニメーションを行っているものもサンプルスクリプトの中にはありましたので
また機会があれば調査して、紹介させて頂ければと思います。

免責事項

※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください。
Pocket

コメント

コメントはありません

コメントフォーム

コメントは承認制ですので、即時に反映されません。ご了承ください。

*