勉強しないとな~blog

ちゃんと勉強せねば…な電気設計エンジニアです。

OpenCVやってみる - 47. PythonでGUI

前回の続きです。
春のパン祭りアプリをexe化する前に、PythonGUIを作れるようにしておきます。

今回の記事はJupyter notebookでやった内容の貼り付けです。

Tkinter試し

PythonGUI作成するのに、いくつか良く使われるライブラリがあるようですが、今回はTkinterを使ってみます。Pythonインストール時に標準で付いてくるそう。

まずは簡単なGUIを動かしてみる。
以下を参考にしました。

https://python.keicode.com/advanced/tkinter.php

import tkinter

まずはテスト。

tkinter._test()

こんな画面が出ました。

"Click me!"したらカッコが増えた。

バージョン確認も。

tkinter.Tcl().eval('info patchlevel')
'8.6.9'

GUI基本(テキスト表示、文字入力、ボタン)

だいたい下記の通りに。
1点だけ、このサイトではfrom tkinter import *としていますが、今回はこれはなしにしておきます。

Tkinter で GUI を作る基本 - Tkinter による GUI プログラミング - Python 入門

from tkinter import ttk
root = tkinter.Tk()
root.title('My first app')
''
frame1 = ttk.Frame(root, padding=16)
label1 = ttk.Label(frame1, text='Your name')
t = tkinter.StringVar()
entry1 = ttk.Entry(frame1, textvariable=t)
button1 = ttk.Button(frame1, text='OK', command=lambda: print('Hello %s' % t.get()))
frame1.pack()
label1.pack(side=tkinter.LEFT)
entry1.pack(side=tkinter.LEFT)
button1.pack(side=tkinter.LEFT)
root.mainloop()
Hello tekitou tarou

できました。
ウィンドウのxボタンを押すまでは、Jupyterのセルが実行中になっていました。

少しだけ試し

また、アプリケーションのルート要素は、アプリケーションを終了したら消えるよう。 なので、作り直します。

tkinter.Frame()ではpaddingのオプションはなく、代わりにpadxpadyがあるようでした。

root = tkinter.Tk()
root.title('My second app')

frame1 = tkinter.Frame(root, padx=30, pady=20)
label1 = tkinter.Label(frame1, text='Your name')
t = tkinter.StringVar()
entry1 = tkinter.Entry(frame1, textvariable=t)
button1 = tkinter.Button(frame1, text='OK', command=lambda: print('Hello %s' % t.get()))

frame1.pack()
label1.pack(side=tkinter.LEFT)
entry1.pack(side=tkinter.LEFT)
button1.pack(side=tkinter.LEFT)

root.mainloop()
Hello tarou tekitou

これだけだといまいち違いが分からないな…

とりあえずこれで基本的なところは押さえられたかなと。

画像表示

Labelでも画像表示できるようでしたが、 試し画像としてjpeg画像を使おうとしたら、対応はしていないようでした。

調べたところ、CanvasウィジェットPILライブラリを使った方法は見つかったので、それでやってみます。

【Python】Tkinterによる画像表示をわかりやすく解説 | ジコログ

【Python/tkinter】OpenCVのカメラ動画をCanvasに表示する | イメージングソリューション

ここまではpack()を使ったウィジェット配置をしていましたが、他にgrid()place()を使う方法もあるとのこと。上記サンプルでは、grid()を使っていました。ここでもgrid()を使ってみました。

【tkinter】grid()を使ったWidgetの配置の方法 - どん底から這い上がるまでの記録

【tkinter】pack()を使ったWidgetの配置の方法 - どん底から這い上がるまでの記録

【tkinter】place()を使ったWidgetの配置の方法 - どん底から這い上がるまでの記録

from PIL import Image, ImageTk, ImageOps
root = tkinter.Tk()
root.title('Image')
root.geometry('400x300')

frame = ttk.Frame(root)
frame.pack()

label_txt = ttk.Label(frame, text='Displaying image')
label_txt.grid(row=0,column=0)

canvas = tkinter.Canvas(frame)
canvas.grid(row=1,column=0)

frame.update() # Needed to get canvas size
w = canvas.winfo_width()
h = canvas.winfo_height()
print(w,h)

if w > 1 and h > 1:
    img = Image.open('harupan_190428_1.jpg')
    img = ImageOps.pad(img, (w,h))
    img = ImageTk.PhotoImage(image=img)

    canvas.create_image(w/2,h/2, image=img)

root.mainloop()
382 269

なんとか画像が出ました。
参考サイト通りにやらなかったのもあって、結構苦労した…

ここまで

ということで今回はここまで。
次回はカメラ画像をGUIで表示してみます。