Macのtkinter8.5でpngをまともに表示できない→PyenvのPython再インストールでtcl-tkをバージョンアップした

## 概要
MacでPython+TkinterでGUIプログラムをつくろうとしてたときに画像がうまく表示されず、tcl-tkのバージョンを上げようとしたところデフォルトでMacに入っているv8.5が呼び出されてしまうのをどうにかしようとしてつまずいた初歩的なことのメモです。
初歩的なことで結局は **使ってるPythonの再インストールをする**ということでした。
とりあえず経過を書いておきます。

## 前提、環境
* 日時: 2018年12月20日
* OS: macOS 10.13.6
* Pythonの環境とバージョン: anyenvのpyenvの3.7.1
* macOSシステムのプリセットのTcl-Tkの最新バージョン: 8.4, 8.5
* Tcl-Tkの現時点の最新バージョン: 8.6.8

## 1. はじめに（Tkinterについて）

TkinterはPythonでtkのGUIを構築するための標準ライブラリ。
Python.orgによるドキュメントページは一応このあたり
- [tkinter --- Tcl_Tk の Python インタフェース — Python 3.7.2rc1 ドキュメント](https://docs.python.org/ja/3/library/tkinter.html?highlight=tkinter#module-tkinter)
- [TkInter - Python Wiki](https://wiki.python.org/moin/TkInter)
ですが、そもそもGUIの説明なのにビジュアルでの情報が整理されている網羅的なドキュメントが本当に少ない:cry:
視覚優位の人間なので、Qiitaや個人サイトでまとめてくださっている方の記事を重宝してなんとか手をつけ始めました。

ちなみに、python2とpython3での書き方が違ったので気をつけてください。
日本語でまとめてくださってる方もいるのですが、python2系3系問題でも違うし、tclとtkのバージョンも最近新しくなってから変わってることもけっこうあるようなので、これからさぐりさぐりやっていきます。

## 2. Tkinterでpng画像を表示したいがうまく表示できない:anguished:
[PythonのTkinterを使ってみる by @nnahito ](https://qiita.com/nnahito/items/ad1428a30738b3d93762)
[コピペでできる！Tkinter](https://nnahito.gitbooks.io/tkinter/content/)

このあたりの記事をみながらいろいろ試してたのですが、png画像ファイルを使いたいので表示させようとしたら、

```console
TypeError: __str__ returned non-string (type Image)
```
というエラーが。とりあえずpngを渡した変数が`Image`オブジェクトとして認識できないとわかり、他のpng画像も複数試しましたが同じでした。pngをgifに変換して使うことも考えましたが、圧縮によって見た目がきれいでなくなるのを避けたいのでどうにかpngでできる方法を探すことにしました。

## 3. Pillow(PIL)など他のパッケージモジュールを使う方法でも透過画像を正しく表示できない:anguished:

"GIFかPPM/PNM形式ファイルを基本的に想定している"との記述を見かけ（※下に書きますがv8.6ではpng等もサポートされてます）、これらの記事

[Python3 + Tkinter のメモ by @narupo](https://qiita.com/narupo/items/04e02093f08142fa8f1a)
[PythonのTkinterでGUIアプリを作る by @canard0328 ](https://qiita.com/canard0328/items/5ea096352e160b8ececa)

などを参考に、Imageを扱うときはPIL(Pillow)を使った方法がよいとのことで試していました。

しかし、Macのtcl-tk8.5にいろいろ問題があるようで、

```python:image.py
img = ImageTk.PhotoImage(Image.open('img.png'))
```

としただけでは少なくとも透過されている=アルファ値を持つ（rgba）png画像データを使うと、エラーは返さないのに、実行すると画像の場所が全く表示されないという状態になりました。そこで、
[Python - PythonのCanvasに画像が表示されない｜teratail](https://teratail.com/questions/85640)
を参考に、

```python:image.py
img = ImageTk.PhotoImage(Image.open('img.png').convert('RGB'))
```
としたところ、確かに画像が表示されるようになりました。しかし、

<img width="100" alt="gizagiza.png" src="https://qiita-image-store.s3.amazonaws.com/0/234874/9b77a500-a785-79be-797a-96c545c8ef95.png">

このように透過であるはずのa値のかかっていた部分が白ならまだしも黒くなり、しかも輪郭がギザギザになるという、OSネイティブなきれいなGUIを作れそうなところに魅力を感じてTkinterに手を出したのにこんなことではとてもこれでやっていくわけにはいかないな…ということになり、ちゃんとドキュメントみてどうにかしようと決意しました。

## 4. Macでのtcl-tk8.5の問題が原因ぽいので最新版8.6にアップデートを試みる:anguished:
[TkDocs - Tk Tutorial - Fonts, Colors, Images](https://tkdocs.com/tutorial/fonts.html#images)
こちらでは、MacのPIL/Pillowが吐くエラーに関して言及していますが、自分のエラーとは違いました。
それにしてもどこをさがしてもtcl-tk8.5のmacでの問題がいろいろあるっぽかったのと、ちゃんと公式[Python.org](https://docs.python.org/ja/3/library/tkinter.html?highlight=tkinter#images)をみたら、バージョン8.6からはPGM、PPM、GIF、PNG形式に対応しているとの記述がありました。
バージョン確認のため、

```console
$ python -m tkinter 
```
または、

```console
$ python3 -m tkinter 
```
と入力すると、tkinterのGUIの小さな画面が立ち上がるのですがこれが`Tsl/Tk version 8.5 `だと言うのでtcl-tkのアップデートを試みます。

## 5. :beer:Homebrewさん「tcl-tkならすでに8.6で最新ですけど」:open_mouth:
Macでtcl-tkの8.5が呼び出されてしまう問題はいろんな人が遭遇してるので、いろいろなところに、
HomebrewでのPython自体のアンインストールと再インストールによる方法が言及されてました。

```console
$ brew uninstall python #あるいはbrew uninstall --ignore-dependencies python
$ brew install tcl-tk #最新版か要確認
$ brew install python --with-tcl-tk
```
python3なら下記

```console
$ brew uninstall python3 #あるいはbrew uninstall --ignore-dependencies python3
$ brew install python3 --with-tcl-tk
```
しかし………

```console
$ python -m tkinter 
```
先程と同じくtcl/tkは8.5とのこと:sweat:
tcl-tkの8.6にPATHが通らない…。PATHの問題かと思ってprofileファイルや環境変数について調べたりして結構時間を使ってしまいました。

## 6. 【解決した】自分の環境ではpyenvでの再インストールだった…:sweat_smile:

[macOS(Mojave)でNo module named ‘_tkinter’を解決する(pyenv , Python3.x)](https://murabitoleg.com/mac-tkinter/)
[Mac OS X 10.11.3 (El Capitan) + pyenv + Python 3.5.1でimport tkinterできない時 by @hokkun_dayo](https://qiita.com/hokkun_dayo/items/223b1125b814621a0c0e)

やったことは上記の記事と同じです。import自体はできてたのですが、pyenvでの再インストールってのを早くやればよかっただけです。

```console
$ pyenv uninstall 3.7.1
$ brew info tcl-tk #バージョンが8.6以上か確認
$ pyenv install 3.7.1
```

インストール済みパッケージをバックアップしておきたかったら
`pip freeze`コマンドで事前にバックアップしておきます。
これで、ようやく、

```console
$ python -m tkinter 
```
と打ち込むと、
<img width="290" alt="tkinter_version.png" src="https://qiita-image-store.s3.amazonaws.com/0/234874/09142bcd-e416-98b1-afab-c04b07fc48cd.png">
`Tcl/Tk version 8.6 ` :tada:やったー！
png画像に関しては
<img width="103" alt="tkinter_beautiful.png" src="https://qiita-image-store.s3.amazonaws.com/0/234874/5d78dbaf-28f4-13b1-1327-312fdb2e0fcf.png">
よし、問題ないです（今回アイコン用画像で試してるのでそもそも画像が小さいがもっと解像度高い画像使えばちゃんときれいになるはず）。
やっと本題のプログラム製作にかかれる……。
HomebrewやPyenvでのパッケージ/バージョン管理は便利なのに、全体のリンキングの構造をちゃんと把握できてないと何の問題かすぐに分からなくて混乱してしまいましたがこれでスタート地点にたてました。

## 他に参考になったページ
[お気楽 Python/Tkinter 入門](http://www.geocities.jp/m_hiroi/light/pytk01.html)
[鎖プログラム Python入門 GUI](https://pg-chain.com/category/python/gui)
[Python：処理ファイルをGUIから選択する方法](https://qiita.com/chanmaru/items/1b64aa91dcd45ad91540)
[Pythonで簡単なGUIを作れる「Tkinter」を使おう by @SquidSky ](https://qiita.com/SquidSky/items/90eb450310f1697d03e9)
[Tkinter による GUI プログラミング - Python 入門](https://python.keicode.com/advanced/tkinter.php)
[Pythonでファイル処理のGUIプログラムを作ってみた！](https://qiita.com/chanmaru/items/8e5ebf7d8b0b21c8fd3a)
[Python Lake](http://www.pythonlake.com/python/tkinter)
[GUI Tk « Python](http://www.java2s.com/Code/Python/GUI-Tk/CatalogGUI-Tk.htm)
[TkinterによるPythonのGUIプログラミング - nobUnagaの日記](http://nobunaga.hatenablog.jp/entry/2018/06/16/173234)
[FrameとLabelFrameの違い【python tkinter sqlite3で家計簿を作る】 - memopy](http://memopy.hatenadiary.jp/entry/2017/05/28/114022)

### *追記
tkinter触り始めたばかりなのでまだまだ調べてるといろいろな情報が出てくる。
[python.orgの25. Tk を用いたグラフィカルユーザインターフェイス](https://docs.python.jp/3/library/tk.html)に書いてあるように、 
> tkinter を使うために Tcl コードを書く必要はありませんが、Tk のドキュメントや、場合によっては Tcl のドキュメントを調べる必要があるでしょう

ここ大事。

それから、Python.orgが紹介している参考文献の中でもTkDocsは結構良いのですが、さらに、
[ニューメキシコ工科大学コンピュータセンターのTkinter 8.5 reference: a GUI for Python](http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html)
[Tcler's wiki](https://wiki.tcl-lang.org/page/Ttk?R=0)
は結構良さそう。ttkのwidget classのstyleのデフォルトの名前などが一覧で書いてあるし、reference全体がPDFにもまとまってます。
スタイルのサンプル
[Python ttk.Style() Examples](https://www.programcreek.com/python/example/81907/ttk.Style)
テーマのサンプル
[Python 2.7 - ttk module seemingly not working in Windows 8.1 - Stack Overflow](https://stackoverflow.com/questions/29690484/python-2-7-ttk-module-seemingly-not-working-in-windows-8-1)
[bitWalk's_ Tk themed widgets](http://bitwalk.blogspot.com/2007/12/tk-themed-widgets.html)
[Py In My Eye](https://pyinmyeye.blogspot.com/2012/07/tkinter-themes-demo.html)
[Python3のtkinterによるクロスプラットフォームGUIアプリ作成入門 - MyEnigma](https://myenigma.hatenablog.com/entry/2017/09/15/150945)
また時間あるときにビジュアルのテストして日本語で備忘録書いていきたいと思います。