Tkinterでデスクトップマスコット的なものを作る。

# Tkinterだって色々できるもん。
Tkinterは難しい、色々できないなどでQtとかKivyとかを使おうみたいな流れがあったりWeb系の方が楽だーみたいな。そういうのありますよね、わたしもそういう流れを一通り体験したような気がします。*（遠い目）*

個人的には現在HTMLに匹敵するほどのことをTkinterで出来るようになってWebアプリをTkinterで作り直そうかみたいな感じになっていたりしてコツさえ分かればTkinterってのはとてもパワフルだし何しろ組み込まれているし動作軽いし、いいことばかり。

そんなところを一人でも多くの人に伝えられたらいいなと思い何かできないかとコードを起こしてみました。

## デスクトップマスコット的な
Pythonを学習しているという方はよく目にしますが目標みたいなものが思いつかずなぞって「ふーん（？）」という感じにフェードアウトしそうな危うさなんてものを感じます。

何かに使えそうな面白そうなものはないかなーと考えてデスクトップマスコットだとかデスクトップウィジットとかのひな型に使えそうなもの。用意してみました。

## 前提
- Windowsのみ

機種依存の機能を利用しているのでWindowsのみの対応となります。
## コード

```python
import tkinter as tk

class Mascot:

    """
     events
    """
    # These events handle dragging the window.
    def mouseDown(self, e):
        if e.num == 1:
            self.origin = (e.x, e.y)
            self.isMouseDown = True

    def mouseRelease(self, e):
        self.isMouseDown = False

    def mouseMove(self, e):
        if self.isMouseDown:
            buf = self.root.geometry().split("+")
            self.setPos(e.x - self.origin[0] + int(buf[1]),
                        e.y - self.origin[1] + int(buf[2]),
                        )

    # The application is terminated by pressing the "ESC" key.
    def keyReleease(self, e):
        if e.keycode == 27:
            self.root.destroy()

    """
     set geometry, Position
    """
    def setPos(self, x, y):
        self.root.geometry("+%s+%s" % (x, y))

    """
     load image, and drawing to canvas
    """
    def dispImage(self, path):
        self.canvas.delete("all")
        self.image = tk.PhotoImage(file=path)
        self.canvas.create_image(0, 0, image=self.image, anchor="nw")

    """
     create main window
    """
    def screenInit(self):
        # Set window size
        self.root.geometry("100x100")

        # Create canvas and drawing image
        self.canvas = tk.Canvas(self.root, bd=0, highlightthickness=0, bg="#003300")
        self.canvas.pack(fill="both")
        self.dispImage("res/python.png")

        """
         Various settings
        """
        # Transparency setting
        self.root.wm_attributes("-transparentcolor", self.canvas["bg"])

        # Disable window decoration
        self.root.overrideredirect(True)

        # Fix the screen to the front
        self.root.attributes("-topmost", True)

        """
         Bind events
        """
        self.canvas.bind("<Button>", self.mouseDown)
        self.canvas.bind("<ButtonRelease>", self.mouseRelease)
        self.canvas.bind("<Motion>", self.mouseMove)
        self.root.bind_all("<KeyRelease>", self.keyReleease)


    def __init__(self):
        self.origin = (0, 0)
        self.isMouseDown = False

        self.root = tk.Tk()
        self.screenInit()
        self.root.mainloop()

if __name__ == "__main__":
    m = Mascot()
```

### 画像
画像はpng形式で端がアンチエイリアスの掛かっていないものにしましょう。

![python logo](https://user-images.githubusercontent.com/12671694/141116501-37d0d92c-687b-4e9d-833c-bca443da43e4.png)

こんなのをでっち上げてみました。

今回は画像を一つだけ使っていますが、複数の画像を読み込んでおいて場合によって切り替えるなんてのも当然できると思います（ハズです（汗））

### 動作イメージ

![running desktop mascot](https://user-images.githubusercontent.com/12671694/141116414-1d45d9ce-8997-4a5c-b856-682986ea8040.png)

最前面に鎮座して、マウスでドラッグできます。
今回は機能的にそれだけです。
ESCキーを押すと終了します。

## コードの解説。
- ウィンドウのデコレーションを消す
- ウィンドウを透過設定
- ウィンドウを最前面に表示

これらがある以外は普通のTkinterを使ったアプリと変わりはありません。
そのあたりは```screenInit```の中の3行で設定しています。

```python
        """
         Various settings
        """
        # Transparency setting
        self.root.wm_attributes("-transparentcolor", self.canvas["bg"])

        # Disable window decoration
        self.root.overrideredirect(True)

        # Fix the screen to the front
        self.root.attributes("-topmost", True)
```

- メニューバーがないので動かせない

ということになるので画像をドラッグできるようにするのも大切なところかもしれません。

```python
        """
         Bind events
        """
        self.canvas.bind("<Button>", self.mouseDown)
        self.canvas.bind("<ButtonRelease>", self.mouseRelease)
        self.canvas.bind("<Motion>", self.mouseMove)
        self.root.bind_all("<KeyRelease>", self.keyReleease)
```
イベントを登録して

```python
    """
     events
    """
    # These events handle dragging the window.
    def mouseDown(self, e):
        if e.num == 1:
            self.origin = (e.x, e.y)
            self.isMouseDown = True

    def mouseRelease(self, e):
        self.isMouseDown = False

    def mouseMove(self, e):
        if self.isMouseDown:
            buf = self.root.geometry().split("+")
            self.setPos(e.x - self.origin[0] + int(buf[1]),
                        e.y - self.origin[1] + int(buf[2]),
                        )

    # The application is terminated by pressing the "ESC" key.
    def keyReleease(self, e):
        if e.keycode == 27:
            self.root.destroy()
```
中身を実装しました。

一見難しそうに見えたりもするのかもしれませんがやってることはとても簡単です。

```mouseDown``` の中では ```e.num``` （押されたマウスボタンの番号）が1として左クリックのみの処理を書いてあります。
右クリックされた場合とかをここに追加してゆけば様々な機能が追加できそうです。

## 次なる目標
現在はマウスでPythonのロゴを動かせるだけですのでここに何かしらの機能を追加してゆこうと思っています。