[PySide] SVGファイルで四角じゃないボタンを作る 基本編

四角じゃないアイコンを作る時に、別途Pathを用意しておいてそれを
PainterPathで使用して使えないかなーというので調べつつ、試しにやってみました。

カーブを扱う場合はどうしたら良いか色々しらべてみた結果「SVG」形式というのを
使用すると良さそうだったので、今回はSVGを使用してみました。

SVGファイルとは?

SVGファイルの良いところは、ファイル形式がXMLで書かれているところ。
Pythonのパーサーも存在はしていますが、XMLなのである程度自分でカバーできるのが
良いですね。

とりあえず、長いですが全コード。

☆画像は→これ

PySideでSVGを使用する場合は、デフォルトで「QGraphicsSvgItem」というSVGを配置するためのアイテムが存在していますが
これだけだと、クリックしたときに何かを実行するなどが出来ないため
↑クラスを継承したSVG_button()クラスを作成します。

ただ配置するだけなら、mousePressEvent()をオーバーライドしてやるだけでOKなのですが
boundingRect

それだけだと、↑のようなSVGの画像ファイルすべて(boundingRect)がクリック対象となってしまいます。
これじゃあ、四角のボタンと何ら変わらなくて(´・ω・`)なので
shape()関数をオーバーライドしてshape内にクリックされたときのみ、mousePressEvent()を
実行するようにします。

shapeはPainterPathで指定するので
SVGからベジェ曲線の座標を取得してあげる必要があるのですが….素直なやり方がなかったので
少々苦戦しました。
※ とりあえず、今回はシンプルなSVGファイルである前提でざっくりと作ってます。

手順は

  1. XMLをパースして、pathエレメントのアトリビュート(d)の内容を取得する
  2. svg.pathモジュールを使用して、Path.d の内容を解析
  3. 解析結果はcomplexで帰ってくるので、実数部→X、虚数部→Yとして値を取得
  4. shape関数内でPainterPathを作成

こんな感じです。
まさかこんなところで虚数と出くわすとは…恐ろしい…数学恐ろしい…
SVGのパースに使用したsvg.pathは、デフォルトでは入っていないモノなので
pip install svg.path
でインストールします。

最後に、shape()関数で、↑で取得してきた座標でshapeを書きます。
QPainterPathは、始点をmoveTo()で決定した後
直線ならlineTo(end_point)
ベジェ曲線ならcubicTo(p1,p2,end_point)
で、ポイントを描画していきます。
(ベジェ曲線を試すためにハートにしてみたものの、EndPointのところが上手く出来なかったのはなんでだろう…)

とりあえずこれで、☆の黄色い部分をクリックするとHello World!!がプリントされるボタンができました。

やった後に気がつきましたが、描画部分を時前で書くのなら、あえてQGraphicsSvgItem使う必要ないよね…というかsetPenしたりBrushしたりすればプログラム内で色が変更できるので
ホバーすると色変更とかクリックしたら色変更とかやりやすいので
あとで、GraphicsItemで書き直そうと思います ズサーc⌒っ゚Д゚)っ

描画周りはまだまだ遊び所満載で楽しいですね、もうちょっとがんばろう。

コメントを残す

メールアドレスが公開されることはありません。


*