Tkinter CookBook　～簡易画像ビューワー～

#Tkinter CookBook4

#前提

###1. 実行環境
本ページで記載しているプログラムコードは**Windows10**, **python3.6**で実行できることを確認しています。

###2. 必要なpythonモジュール
下記のモジュールを別途インストールしておく必要があります。

* **PIL**

###3. 本投稿の目的
tkinterで小さな部品をどんどん作っていこうと思います。
今回は画像を表示するGUIを作ります。
ただそれだけです！

#それでは、はじめましょう。

```python:ImageViewer.py
import tkinter as tk
from PIL import Image, ImageTk

class ImageViewer:
    def __init__(self, root):
        self.label = tk.Label(root)
        self.label.grid(column=0, columnspan=2, row=1)

        self.entry = tk.Entry(root)
        self.entry.grid(column=0, row=0)
        self.entry["font"] = ("Helvetica", 20)

        self.button = tk.Button(root)
        self.button.grid(column=1, row=0)
        self.button["width"] = 10
        self.button["text"] = "表示"
        self.button["font"] = ("Helvetica", 20)
        self.button["command"] = self.setImage

    def setImage(self, event=None):
        img = Image.open(self.entry.get())
        self.image = ImageTk.PhotoImage(img.resize((500,500)))
        self.label["image"] = self.image
        self.label.image = self.image

if __name__=="__main__":
    root = tk.Tk()
    imageViewer = ImageViewer(root)
    root.mainloop()
```

実行すると下記のようなウィンドウが起動します。
![ImageViewer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302006/7de70e7f-ceaa-ecf3-f267-c2c86d64f5e6.png)

パスを入れ、表示と書かれたボタンを押すと、
![ImageViewer2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302006/1c611f4d-dfbe-431f-3110-0f930b4a5b51.png)
画像を表示します。（これだけです。）

このプログラムが行っていることは

1. **「Label」**,**「Entry」**,**「Button」**オブジェクトを配置
2. ボタンが押された際に**「Entry」**オブジェクト内に入力されている文字列を取得し、その文字列に記載されているパスの画像を表示

です。

## 1.**「Label」**,**「Entry」**,**「Button」**オブジェクトを配置

```python
def __init__(self, root):
        self.label = tk.Label(root)
        self.label.grid(column=0, columnspan=2, row=1)

        self.entry = tk.Entry(root)
        self.entry.grid(column=0, row=0)
        self.entry["font"] = ("Helvetica", 20)

        self.button = tk.Button(root)
        self.button.grid(column=1, row=0)
        self.button["width"] = 10
        self.button["text"] = "表示"
        self.button["font"] = ("Helvetica", 20)
        self.button["command"] = self.setImage
```
**tk.ウィジェット名（親オブジェクト名）**で各オブジェクト（ラベル、ボタン、エントリー）を作成しています。

**「Button」**は**command**属性にメソッド**self.setImage**を指定しています。ボタンが押されるとこのメソッドが呼び出されます。

また**「Label」**オブジェクトを**grid**メソッドによって配置する際に**columnspan**という引数を指定しております。
![column.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302006/ae55779d-f646-3f26-dc06-e55e4401d14e.png)
上図のように**column=0**にはエントリーオブジェクト、**column=1**にはボタンオブジェクトが配置されており、その下に画像を配置したいとします。このときに、画像は**column=0および1**をまたぐ必要があります。その指定が**columnspan**です。
**columnspan=2**とすることで2つの**column**にまたがることが出来ます。

##2. ボタンが押された際に**「Entry」**オブジェクト内に入力されている文字列を取得し、その文字列に記載されているパスの画像を表示

```python
def setImage(self, event=None):
    img = Image.open(self.entry.get())
    self.image = ImageTk.PhotoImage(img.resize((500,500)))
    self.label["image"] = self.image
    self.label.image = self.image
```
単純に画像を表示するだけであれば、**PIL**モジュールをインポートする必要はないです。
**PIL**モジュールを入れた目的は画像のリサイズです。表示する画像のサイズが一定であると良いかなと思い、そのようにしました。

まず**PIL**で画像を開くには**Image.open(画像のパス)**とします。
上記のコードではパスを**self.entry.get()**で取得します。**get()**はエントリーオブジェクト内に入力された文字列を取得するメソッドです。

また**PIL**で開いた画像を**tkinter**で使用する場合は**ImageTk.PhotoImage**を使用します。上記のコードでは合わせて画像のリサイズを行うメソッド**resize((x_size, y_size))**を使用しています。

最後に**「Label」**オブジェクトの**image**属性に**ImageTk.PhotoImage**オブジェクトを指定します。

*tkinterのPhotoImageオブジェクトはpythonのガーベッジコレクトによってクリアされてしまいます。ここでは念の為self.label.imageもImageTk.PhotoImageオブジェクトを参照するようにしています。
"image"属性だけでPhotoImageオブジェクトを参照している場合は画像が表示されない場合があります。
http://effbot.org/tkinterbook/photoimage.htm*

##以上です！

##他のTkinter Cookbook
[家計簿　作成中・・・](https://qiita.com/The-town/items/3bd1fcf5ee26242ed877)
[フォント](https://qiita.com/The-town/items/b518d8b6b97e8acf98b3)
[タイマー](https://qiita.com/The-town/items/be391ff799f95dab8b96)