Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

概要

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 ドキュメント
- TkInter - Python Wiki
ですが、そもそもGUIの説明なのにビジュアルでの情報が整理されている網羅的なドキュメントが本当に少ない:cry:
視覚優位の人間なので、Qiitaや個人サイトでまとめてくださっている方の記事を重宝してなんとか手をつけ始めました。

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

2. Tkinterでpng画像を表示したいがうまく表示できない:anguished:

PythonのTkinterを使ってみる by @nnahito
コピペでできる!Tkinter

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

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
PythonのTkinterでGUIアプリを作る by @canard0328

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

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

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

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

image.py
img = ImageTk.PhotoImage(Image.open('img.png').convert('RGB'))

としたところ、確かに画像が表示されるようになりました。しかし、

gizagiza.png

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

4. Macでのtcl-tk8.5の問題が原因ぽいので最新版8.6にアップデートを試みる:anguished:

TkDocs - Tk Tutorial - Fonts, Colors, Images
こちらでは、MacのPIL/Pillowが吐くエラーに関して言及していますが、自分のエラーとは違いました。
それにしてもどこをさがしてもtcl-tk8.5のmacでの問題がいろいろあるっぽかったのと、ちゃんと公式Python.orgをみたら、バージョン8.6からはPGM、PPM、GIF、PNG形式に対応しているとの記述がありました。
バージョン確認のため、

$ python -m tkinter 

または、

$ 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自体のアンインストールと再インストールによる方法が言及されてました。

$ brew uninstall python #あるいはbrew uninstall --ignore-dependencies python
$ brew install tcl-tk #最新版か要確認
$ brew install python --with-tcl-tk

python3なら下記

$ brew uninstall python3 #あるいはbrew uninstall --ignore-dependencies python3
$ brew install python3 --with-tcl-tk

しかし………

$ 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)
Mac OS X 10.11.3 (El Capitan) + pyenv + Python 3.5.1でimport tkinterできない時 by @hokkun_dayo

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

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

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

$ python -m tkinter 

と打ち込むと、
tkinter_version.png
Tcl/Tk version 8.6 :tada:やったー!
png画像に関しては
tkinter_beautiful.png
よし、問題ないです(今回アイコン用画像で試してるのでそもそも画像が小さいがもっと解像度高い画像使えばちゃんときれいになるはず)。
やっと本題のプログラム製作にかかれる……。
HomebrewやPyenvでのパッケージ/バージョン管理は便利なのに、全体のリンキングの構造をちゃんと把握できてないと何の問題かすぐに分からなくて混乱してしまいましたがこれでスタート地点にたてました。

他に参考になったページ

お気楽 Python/Tkinter 入門
鎖プログラム Python入門 GUI
Python:処理ファイルをGUIから選択する方法
Pythonで簡単なGUIを作れる「Tkinter」を使おう by @SquidSky
Tkinter による GUI プログラミング - Python 入門
Pythonでファイル処理のGUIプログラムを作ってみた!
Python Lake
GUI Tk « Python
TkinterによるPythonのGUIプログラミング - nobUnagaの日記
FrameとLabelFrameの違い【python tkinter sqlite3で家計簿を作る】 - memopy

*追記

tkinter触り始めたばかりなのでまだまだ調べてるといろいろな情報が出てくる。
python.orgの25. Tk を用いたグラフィカルユーザインターフェイスに書いてあるように、

tkinter を使うために Tcl コードを書く必要はありませんが、Tk のドキュメントや、場合によっては Tcl のドキュメントを調べる必要があるでしょう

ここ大事。

それから、Python.orgが紹介している参考文献の中でもTkDocsは結構良いのですが、さらに、
ニューメキシコ工科大学コンピュータセンターのTkinter 8.5 reference: a GUI for Python
Tcler's wiki
は結構良さそう。ttkのwidget classのstyleのデフォルトの名前などが一覧で書いてあるし、reference全体がPDFにもまとまってます。
スタイルのサンプル
Python ttk.Style() Examples
テーマのサンプル
Python 2.7 - ttk module seemingly not working in Windows 8.1 - Stack Overflow
bitWalk's_ Tk themed widgets
Py In My Eye
Python3のtkinterによるクロスプラットフォームGUIアプリ作成入門 - MyEnigma
また時間あるときにビジュアルのテストして日本語で備忘録書いていきたいと思います。

undead
デザインとエンジニアリング修行中。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away