PySideでFontAwesomeを使おう(Hi-DPIアプリケーション対応)


はじめに

こちらはMaya Advent Calendar 2018の12月1日の記事です。

(ちょっと時間が取れず、スクショが少なくてごめんなさい。後日更新します)

4Kモニター使いましょう。そしてDPIを上げましょう。

今回使う環境
* Windows10
* Maya2018
* PySide2

ビットマップイメージの問題点

PySide(Qt)は(基本的には)自動でDPIを判断し、ボタンや文字のサイズを変更してくれます。

ただしビットマップイメージを表示した場合は、当然のことながら拡大してしまうとドットが見えてしまいます。
十分な解像度でビットマップイメージを作成しておくのも解決策の一つですが、今後も4K、8KとDPIは上がり続けます。現時点では十分な解像度だとしても将来的には足りなくなる可能性があります。

分かりやすいようにアイコン表示したいですよね。
美しく表示するためには、画像データはベクトルデータに変更する時代となりました。

身近なベクトルデータの代表格”フォント”

画像をベクトルデータに変更しようと思ったら、SVGで用意することになるかと思います。面倒ですね。

ベクトルデータ・・・ベクトルデータ・・・あっ!フォントってベクトルデータだよね・・・拡大できるし。

FontAwesomeとは

ウェブアプリケーションでよく使うアイコンが格納されたフォントです。

もちろんQtやMayaは標準的なアイコンは用意してくれていますが、充実度が違いすぎます。感謝。

Free版とPro版が存在するのですが、Free版はフォントそのものを単体で販売しない限りは自由に使えるライセンスとなってます。詳しくは本家を参照してください。

メニュー・ラジオボタン・チェックボックス・ボタンにアイコンを表示してみようと思います。

QtDesignerでリソースに埋め込む

デスクトップで使用するためにフォントファイルをダウンロードします。
https://fontawesome.com/how-to-use/on-the-desktop/setup/getting-started

リソースエディタでフォントファイルを読み込みます。指定しやすいように別名もつけておきましょう

フォントを有効にする

ここから先はPythonです。

あらかじめuiやqrcをpythonファイルに変換するとかは今回割愛して、フォントの初期化をします。

リソースを指定してフォントデータベースに登録します。


FONT_AWESOME_SOLID = u"Font Awesome 5 Free Solid"
FONT_AWESOME_REGULAR = u"Font Awesome 5 Free Regular"
FONT_AWESOME_FAMILY_NAMES = {
    FONT_AWESOME_SOLID: u":/main/FontAwesomeSolid.otf",
    FONT_AWESOME_REGULAR: u":/main/FontAwesomeRegular.otf",
}

def main():
    for family, resource in FONT_AWESOME_FAMILY_NAMES.items():
        _font_id = QtGui.QFontDatabase.addApplicationFont(resource)
        if _font_id < 0:
            raise FontAwesomeError(
                u"Can't load FontAwesome font. ({0})".format(family))
        _family_name = QtGui.QFontDatabase.applicationFontFamilies(_font_id)[0]
        if _family_name != family:
            raise FontAwesomeError(
                u"Invalid FontAwesome family name. ({0})".format(_family_name))

各ウィジェットのラベルに割り当てる

Pythonでラベルを指定します。

その際にキャラクターコードをダイレクトに指定します。文字コードはfontawesomeのサイトで簡単に調べられます。


FONT_AWESOME_CHAR_FILE_IMAGE = u"\uf1c5"
FONT_AWESOME_CHAR_ALIGN_LEFT = u"\uf036"
FONT_AWESOME_CHAR_ALIGN_CENTER = u"\uf037"
FONT_AWESOME_CHAR_ALIGN_RIGHT = u"\uf038"
FONT_AWESOME_CHAR_THUMBTACK = u"\uf08d"
FONT_AWESOME_CHAR_COGS = u"\uf085"
FONT_AWESOME_CHAR_ARROW_ALT_CIRCLE_RIGHT = u"\uf35a"

class MainWindow(MayaQWidgetBaseMixin, QtWidgets.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        # フォントアイコンを設定
        font = QtGui.QFont()
        font.setFamily(FONT_AWESOME_SOLID)

        self.action_open.setFont(font)
        self.action_open.setText(FONT_AWESOME_CHAR_FILE_IMAGE + u" 開く")

        self.radio_left.setFont(font)
        self.radio_left.setText(FONT_AWESOME_CHAR_ALIGN_LEFT)

        self.radio_center.setFont(font)
        self.radio_center.setText(FONT_AWESOME_CHAR_ALIGN_CENTER)

        self.radio_right.setFont(font)
        self.radio_right.setText(FONT_AWESOME_CHAR_ALIGN_RIGHT)

        self.check_flag.setFont(font)
        self.check_flag.setText(FONT_AWESOME_CHAR_THUMBTACK)

        self.button_execute.setFont(font)
        self.button_execute.setText(FONT_AWESOME_CHAR_COGS + u" " + self.button_execute.text())

完成

元のウインドウはこのようなそっけない状態です。

こんな感じになりました。なんか可愛い。

メニューにも指定可能ですが、Mayaはメニューにアイコンを表示する仕組みを持っているのでそれに則った方がよさそうですね。

終わりに

ラベルに指定するだけなので、単色での表示のことしか考えていません。カラフルにしたい場合は別の方法でしっかり対応しましょう。

この方法はお手軽さとユーザーに与える好印象のバランスが良いと思います。

繰り返しになりますが、4Kモニター使いましょう。