tkinterで、自分で用意したカスタムのマウスカーソルを使用する

Python + tkinter で手のひらのマウスカーソルを使いたかったのですが、方法を調べても簡単には見つからなかったのでここにメモしておきます。
Windowsでしか試していませんが、X Windows SystemMac でもできるとのこと。プラットフォームによってやり方はそれぞれ違うみたいです。

結論

Windowsにおける手順は以下の通り。

  1. .cur または .ani 形式のファイルを用意する。
  2. ウィジェットの "cursor" オプションに、@ファイルパス という形式で用意したファイルを指定する。

サンプルソースファイルを以下に示します。
指定するファイルとして C:\Windows\Cursors\earo_busy_xl.ani を指定しています。 お使いのシステムに存在しない場合は適当に修正してください。

import tkinter

if __name__ == "__main__":
    root = tkinter.Tk()
    # メインウィンドウにカーソルが乗ったときに
    # マウスカーソルを組み込みカーソル "hand2" にする
    root.configure(cursor="hand2")

    # ラベル "watch" にカーソルが乗ったときに
    # マウスカーソルを組み込みカーソル "watch" にする
    label = tkinter.Label(root, text="watch", bg="white", cursor="watch")
    label.pack(ipadx=10, ipady=10, padx=20, pady=20)

    # [本題]
    # ラベル "custom" にカーソルが乗ったときにマウスカーソルを
    # ファイル "C:\Windows\Cursors\aero_busy_xl.ani"にする
    label = tkinter.Label(root, text="custom", bg="white",
        cursor="@C:/Windows/Cursors/aero_busy_xl.ani")
    label.pack(ipadx=10, ipady=10, padx=20, pady=20)

    root.mainloop()

注意 パスを記述する際は、区切り文字にスラッシュを使わなければならないようでした。 私は最初にバックスラッシュを使ってしまい、エラーとなってしまいました。

ビルトインカーソルを指定するには

やり方を検索し始めて最初に見つかったサイトが以下です。ほとんどの人はこのサンプルだけで十分だと思います。

Tkinterカーソルの種類(マウスポインターの種類) | 株式会社 石川設計

しかし、私が表示したかった開いた手のひらのアイコンはありませんでした。
私は思いました。「でも、ここにあるキーワードですべてなのか?実はほかのカーソルも用意されてたりしないかな?」

ビルトインカーソルの種類

ビルトインカーソルの種類は、結論から言うと、前項のサイトで網羅されているようでした。

tkinterのリファレンスには、以下のように書かれています。

cursor
cursorfont.h の標準Xカーソル名を、接頭語 XC_ 無しで使うことができます。例えば、handカーソル(XC_hand2)を得るには、文字列 "hand2" を使ってください。あなた自身のビットマップとマスクファイルを指定することもできます。 Ousterhout の本の179ページを参照してください。

つまり、cursorに指定できる文字列はソースを見ろ、ということでした。またしても適当に探して見つけた X11 の cursorfont.h は以下です。

include/X11/cursorfont.h · master · xorg / lib / libX11 · GitLab

前項の石川設計さんのサンプルは、上記のヘッダファイルのシンボルをすべて網羅していることがわかります。
ということで、ビルトインカーソルの中に 私がほしい形状は無さそうだ、と結論付けました。

一方で、上記の引用文には「あなた自身のビットマップとマスクファイルを指定することもできます」とあります。まだ手段はありそうです。

X11でカスタムのカーソルを使用するには

以下のQ&Aが見つかりました。

Python Tkinterでカスタムマウスカーソルを作ることは可能ですか? (TkAggバックエンドでmatplotlibを使用する) - CODE Q&A

上記の回答の中に、cursorオプションに(ビルトインカーソルを表す文字列ではなく)4つの要素を持つタプルを指定しているものがあります。「UNIX11 XBMファイル」で動作する、とも。
4要素に何を指定すればよいかはよくわかりませんし、Windowsでは動作しないようにも思いました。

とりあえず cursor オプションにはビルトインの文字列以外も指定できるようです。これまで tkinter をキーワードに調べてきましたが、そのものずばりな解にたどり着けないので、今度は Tcl/Tk をキーワードにして調べることにします。

Tcler's Wiki に記載されていた解

Tcl/Tk をキーワードに入れてたどり着いたのが以下のページです。

custom cursors

上記によれば、-cursor オプションとして以下のような指定ができるのだそう。

  1. name fgColor bgColor
  2. @sourceName maskName fgColor bgColor
  3. @sourceName

2番目の項目が前項のQ&Aにあった指定方法のようです。しかし、その説明には以下のようにあります。

This form of the command will not work on Macintosh or Windows computers.

WindowsMacでは使えません、と。で、3番目の項目に以下のように書かれています。これが答えですね。

@sourceName
This form only works on Windows, and will load a Windows system cursor (.ani or .cur) from the file specified in sourceName.

というわけで、最初に記載したサンプルコードを書いたらめでたく動いてくれました。
以上です。