【Python/tkinter】Checkbutton(チェックボックス)

チェックボタン(チェックボックス)はCheckbuttonクラスによって作成します。

以下にサンプルを示します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.title("チェックボックスの作成")       # ウィンドウタイトル
        self.master.geometry("300x100")                 # ウィンドウサイズ(幅x高さ)

        # チェックボックスの値
        self.check_value = tk.BooleanVar(value = True)  # 初期値を設定する場合
        #self.check_value = tk.BooleanVar()             # 初期値を設定しないとFlaseになる
        # チェックボックスの作成
        self.check = tk.Checkbutton(self.master, 
                           text = "チェックボックス",    # チェックボックスの表示名
                           command = self.check_click,  # クリックされたときに呼ばれるメソッド
                           variable = self.check_value  # チェックの状態を設定する
                           )

        # ボタンの作成
        button = tk.Button(self.master, 
                           text = "チェックを逆にする",  # ボタンの表示名
                           command = self.button_click  # クリックされたときに呼ばれるメソッド
                           )
        # 配置
        self.check.pack()
        button.pack()

    def check_click(self):
        # チェックの状態を取得(チェックされているときはTrue)
        value = self.check_value.get()
        print(f"チェックの状態は {value} です")

    def button_click(self):
        # チェックの状態を取得し逆に設定する
        value = self.check_value.get()
        self.check_value.set(not value)
        #以下のようにしても同じ
        #self.check.toggle()


if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

ポイント

  • チェックボタンの値(チェックされている(True)/されていない(False))はBooleanVarクラスオブジェクトをCheckbuttonクラスのvariableオプションに設定する
  • チェックの状態の取得は BooleanVarクラスオブジェクト.get() で行う
  • チェックの状態の設定は BooleanVarクラスオブジェクト.set() の引数にTrue もしくは False を渡す

オプション

オプション名 説明
activebackground クリックされたときの背景色を指定します。
activeforeground クリックされたときの文字色(チェックマークを含む)を指定します。
anchor 文字の配置位置を指定します。
【設定値】tk.N, tk.S, tk.W, tk.E, tk.NW, tk.NE, tk.SW, tk.SE, tk.CENTER
【初期値】tk.CENTER
※width, heightを指定し、余白が生じている際に有効です。
background 通常時(クリックされていないとき)の背景色を指定します。(bgと同じ)
bd 枠線の太さを指定します。
ただし、初期状態では枠線が表示されていないため、reliefで枠線のスタイルを指定する必要があります。(borderwidthと同じ)
bg backgroundと同じ
bitmap モノクロのBitmapを指定します。
(参考)https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/bitmaps.html
borderwidth bdと同じ
command ボタンがクリックされたときに呼び出すメソッドの名前を指定します。
compound 文字と画像の両方を表示する際に、文字に対して画像の表示位置を指定します。
【設定値】tk.LEFT, tk.RIGHT, tk.BOTTOM, tk.TOP, tk.CENTER
cursor ウィジェット上にマウスポインタがある際のカーソルの種類を指定します。
(参考)https://tkdocs.com/shipman/cursors.html
disabledforeground stateオプションで無効(DISABLED)に設定している際の文字色を設定します。
fg 表示する文字色を指定します。(foregroundと同じ)
font 表示する文字のフォントを指定します。
foreground fgと同じ
height ボタンの高さを文字数で指定します。
画像を配置した時は、画素数の指定になります。
highlightbackground
highlightcolor
highlightthickness
image 表示する画像を指定します。
indicatoron
justify 複数行の文字のときの、文字寄せ方向を指定します。
【設定値】左寄せ(tk.LEFT), 中央寄せ(tk.CENTER), 右寄せ(tk.RIGHT)
offvalue チェックが無い時の値をTrue, Falseで指定します。
【初期値】False
onvalue チェックがある時の値をTrue, Falseで指定します。
【初期値】True
overrelief ウィジェット上にマウスポインタがある際のスタイルを指定します。
【設定値】tk.RAISED, tk.GROOVE, tk.SUNKEN, tk.RIDGE, tk.FLAT
【初期値】tk.FLAT(枠線なし)
padx 文字の両側の隙間を指定します。
pady 文字の上下の隙間を指定します。
relief ボタンのスタイルを指定します。
【設定値】tk.RAISED, tk.GROOVE, tk.SUNKEN, tk.RIDGE, tk.FLAT
【初期値】tk.FLAT(枠線なし)
selectcolor チェックボックス(チェックのある四角)の背景色を指定します。
selectimage
state ウィジェットの有効/無効(操作できない状態)を指定します。
【設定値】tk.NORMAL, tk.DISABLED
【初期値】tk.NORMAL
takefocus
text 表示する文字を指定します。
textvariable
tristateimage
tristatevalue
underline 指定した順番(先頭から0始まり)の文字にアンダーラインを付加します。
variable チェックの状態をBooleanVarクラスオブジェクトで指定します。
width ボタンの幅を文字数で指定します。
画像を配置した時は、画素数の指定になります。
wraplength 文字の折り返し幅を指定します。

 

メソッド

メソッド 説明
deselect() チェックなし状態にします。
flash() backgroundとactivebackgroundで交互に色を点滅させて表示します。
invoke()
select() チェックあり状態にします。
toggle() チェックのあり/なしを逆に設定します。

 

【Python】本家ドキュメントリンク集

Pythonを勉強していて、何か分からなかった時、Googleで検索すればだいたいの情報は出てくると思いますが、とりあえず本家のページで確認して、正しい情報を知りたい!という事で、本家ページのリンク集です。

(随時更新予定です)

 

モジュール 概要
Python(日本語) Pythonのリファレンス、チュートリアルなど
math 数値の切り捨て、切り上げ、絶対値やSin, Cos, PI など
tkinter ウィンドウGUIのリファレンスチュートリアルなど
os 環境変数、ファイルパスの操作(ファイル名、ディレクトリの取得など)
matplotlib
データの可視化、数値データのグラフ表示、画像の表示など
numpy データ配列、乱数、FFT、行列演算など
PIL(pillow) 画像ファイルを開く、保存、画像データの変換など

【Python/tkinter】ファイルを開くダイアログボックスの表示

ファイルを開くダイアログボックスを表示するには、tkinter.filedialogモジュールのaskopenfilename()関数を使います。

以下にシンプルなサンプルプログラムを示します。

from tkinter import filedialog

filename = filedialog.askopenfilename()
print(filename)

(実行結果)

オプション

オプション名 説明
parent ダイアログを表示する親のウィンドウを指定します。
title ダイアログのタイトルを指定します。
initialdir 最初に表示されるディレクトリを指定します。
initialfile 最初に選択されているファイル名を指定します。
filetypes 選択可能なファイルの種類を設定します。
multiple 複数ファイルの選択を許可する場合はTrueを、そうでない場合はFalseを指定します。

(参考)

https://docs.python.org/ja/3/library/dialog.html?highlight=askopenfilename#module-tkinter.filedialog

サンプル

実際に、このダイアログを使用する場合には、title, initialdir, filetypesの3つは指定しておいた方が良いでしょう。

以下に私がよく使うパターンのサンプルを示します。

from tkinter import filedialog

filename = filedialog.askopenfilename(
    title = "画像ファイルを開く",
    filetypes = [("Image file", ".bmp .png .jpg .tif"), ("Bitmap", ".bmp"), ("PNG", ".png"), ("JPEG", ".jpg"), ("Tiff", ".tif") ], # ファイルフィルタ
    initialdir = "./" # 自分自身のディレクトリ
    )
print(filename)

(実行結果)

関連記事

【Python/tkinter】名前を付けて保存ダイアログボックスの表示

【Python/os】カレントディレクトリの取得/設定

カレントディレクトリを取得/設定するにはosモジュールgetcwd() および chdir() を用います。

getcwd カレントディレクトリの取得
chdir カレントディレクトリの設定

 

以下に、カレントディレクトリの取得/設定を繰り返したサンプルを示します。

import os

# カレントディレクトリの取得
current = os.getcwd()
print(current)

# カレントディレクトリの設定(一つ上)
os.chdir("../")

# カレントディレクトリの取得
current = os.getcwd()
print(current)

# カレントディレクトリの設定(直接パスの指定)
os.chdir("c:\\Temp")

# カレントディレクトリの取得
current = os.getcwd()
print(current)

(実行結果)

【Python/tkinter】メッセージボックス

メッセージボックスには、OKボタンが1つのメッセージボックスやOKボタン/Cancelボタンがあるものなど、いくつかのバリエーションがありますが、これらの種類は関数名で切り替えます。

 

まずは、以下のサンプルを実行して頂くと雰囲気がつかめると思います。

from tkinter import messagebox

ret = messagebox.showinfo(
    title = "タイトル",
    message = "showinfoで表示されるメッセージ")
print("showinfoの戻り値:\t", ret)

ret = messagebox.showwarning(
    title = "タイトル",
    message = "showwarningで表示されるメッセージ")
print("showwarningの戻り値:\t", ret)

ret = messagebox.showerror(
    title = "タイトル",
    message = "showerrorで表示されるメッセージ")
print("showerrorの戻り値:\t", ret)

ret = messagebox.askokcancel(
    title = "タイトル",
    message = "askokcancelで表示されるメッセージ")
print("askokcancelの戻り値:\t", ret)

ret = messagebox.askyesno(
    title = "タイトル",
    message = "askyesnoで表示されるメッセージ")
print("askyesnoの戻り値:\t", ret)

ret = messagebox.askretrycancel(
    title = "タイトル",
    message = "askretrycancelで表示されるメッセージ")
print("askretrycancelの戻り値:", ret)

ret = messagebox.askquestion(
    title = "タイトル",
    message = "askquestionで表示されるメッセージ")
print("askquestionの戻り値:\t", ret)

ret = messagebox.askyesnocancel(
    title = "タイトル",
    message = "askyesnocancelで表示されるメッセージ")
print("askyesnocancelの戻り値:", ret)

 

関数名 メッセージボックス 戻り値
showinfo ok
showwarning ok
showerror ok
askokcancel True, False
askyesno True, False
askretrycancel True, False
askquestion yes, no
askyesnocancel True, False, None

 

【Python/tkinter】ウィジェットの配置(pack)

ウィジェットを配置するには、pack,grid,placeの3つのメソッドがありますが、ここではpackについて説明します。(個人的にはpack, grid, placeのうち、packが一番使いやすいと思っています。)

packは、下図のように、ボタンやラベルなどのウィジェットを上、下、左、右方向に積み木のように、重ねて配置します。

 

以下に簡単なサンプルを示します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_top = tk.Button(self.master, text = "TOP", width = 8)
        button_bottom = tk.Button(self.master, text = "BOTTOM", width = 8)
        button_left = tk.Button(self.master, text = "LEFT", width = 8)
        button_right = tk.Button(self.master, text = "RIGHT", width = 8)

        # ウィジェットの配置
        button_top.pack(side = tk.TOP)
        button_bottom.pack(side = tk.BOTTOM)
        button_left.pack(side = tk.LEFT)
        button_right.pack(side = tk.RIGHT)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行画面)

 

構文

ウィジェット.pack(オプション1 = 設定値, オプション2 = 設定値,・・・)

オプション

オプション名 説明
after すでに配置されているウィジェットの次にウィジェットを配置する
anchor sideで示した領域内のウィジェットの配置方向を指定します。
【設定値】tk.N, tk.S, tk.W, tk.E, tk.NW, tk.NE, tk.SW, tk.SE, tk.CENTER
【初期値設定値】tk.CENTER
before すでに配置されているウィジェットの前にウィジェットを配置する
expand ウィジェットを配置する領域を残りの領域全体に広げるかどうかを指定します。
【設定値】True, False
【初期値設定値】False
fill ウィジェットを領域の横、縦、または両方の方向の幅、高さに合わせてに大きくするか?設定します。
【設定値】tk.X, tk.Y, tk.BOTH, tk.NONE
【初期値設定値】tk.NONE
in_ ウィジェット作成時に親ウィジェットを指定せずに、配置時(pack時)に親ウィジェットを指定します。
ipadx ウィジェットの内側の横方向の隙間を設定します。
ipady ウィジェットの内側の縦方向の隙間を設定します。
padx ウィジェットの外側の横方向の隙間を設定します。
値で設定すると、両側の隙間を設定します。
タプルで(左, 右)のように設定すると、それぞれの隙間を指定できます。
pady ウィジェットの外側の縦方向の隙間を設定します。
値で設定すると、上下の隙間を設定します。
タプルで(上, 下)のように設定すると、それぞれの隙間を指定できます。
side ウィジェットの配置方向を、上、下、左、右の中から指定します。
【設定値】tk.TOP, tk.BOTTOM, tk.LEFT, tk.RIGHT
【初期値設定値】tk.TOP

 

side

sideではウィジェットの上下左右の配置方向を指定しますが、配置の順番が重要となります。

最初のプログラムの配置部分(packの部分)のプログラムは

# ウィジェットの配置
button_top.pack(side = tk.TOP)
button_bottom.pack(side = tk.BOTTOM)
button_left.pack(side = tk.LEFT)
button_right.pack(side = tk.RIGHT)

となっていますが、この結果は以下のような感じでした。

この配置の順番を入れ替えて、以下のようなプログラムにすると

# ウィジェットの配置
button_left.pack(side = tk.LEFT)
button_top.pack(side = tk.TOP)
button_right.pack(side = tk.RIGHT)
button_bottom.pack(side = tk.BOTTOM)

実行結果は

のようになり、バラバラな配置になります。
なぜ、このようになるのか?順を追って見ていきます。

最初にボタンを左側にpackしています。

button_left.pack(side = tk.LEFT)

この時点で、目には見えませんが、packした占有領域としては、親ウィジェットの左側の上から下までボタンの幅分、占有されています。

ボタン位置の上下方向はanchorで指定できますが、指定しない場合、初期値の中央(tk.CENTER)が適応されます。

次に配置されるウィジェットは、この残りの領域に対して配置されます。
つまり次のボタンを上側に配置以下のように配置すると、残りの領域の上側が占有されます。

button_top.pack(side = tk.TOP)

同様にして、次に右側に配置すると

button_right.pack(side = tk.RIGHT)

続いて下側

button_bottom.pack(side = tk.BOTTOM)

というように、pack()のsideでは残っている領域の上側、下側、左側、右側の上から下まで、もしくは左から右まで占有している事に注意が必要です。

 

anchor

anchorはsideとも似ているのですが、sideの説明で示した占有領域内(赤く囲った部分)の配置方向を方角を使って指定します。

これを踏まえた上で、以下のプログラムを実行してみます。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_N = tk.Button(self.master, text = "N", width = 8)
        button_S = tk.Button(self.master, text = "S", width = 8)
        button_W = tk.Button(self.master, text = "W", width = 8)
        button_E = tk.Button(self.master, text = "E", width = 8)

        # ウィジェットの配置
        button_N.pack(anchor = tk.N)
        button_S.pack(anchor = tk.S)
        button_W.pack(anchor = tk.W)
        button_E.pack(anchor = tk.E)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

すると、特に、tk.Sを指定した時に違和感がありますよね。
さらに、tk.Wとtk.Eの上下方向がズレてるし。。

これについても、packで占有される領域を示すと理解しやすくなります。

pack()では、sideオプションを指定しないとtk.TOPになるので、全て上側にウィジェットが積み重なります。
anchorオプションはあくまでも、占有領域内の配置方向を指定するので、side = tk.TOP のときは、上下方向の指定(tk.N, tk.S)はtk.CENTERと同様になります。

同様にして side = tk.LEFT もしくは side = tk.RIGHT のときは、左右方向の指定(tk.W, tk.E) も tk.CENTERと同様になります。

ただし、次に示す expand = True とした時は、上下、左右、斜め方向の指定が有効になります。

 

expand

expandは expand = Trueとした時、残っている領域全てを占有領域とします。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_top = tk.Button(self.master, text = "TOP", width = 8)
        button_center = tk.Button(self.master, text = "CENTER", width = 8)

        # ウィジェットの配置
        button_top.pack()
        button_center.pack(expand = True)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

これも占有領域を書くと分かりやすいと思います。

2つ以上のウィジェットを expand = True にして配置すると、領域を均等分割して配置されます。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_top = tk.Button(self.master, text = "TOP", width = 8)
        button_center1 = tk.Button(self.master, text = "CENTER1", width = 8)
        button_center2 = tk.Button(self.master, text = "CENTER2", width = 8)

        # ウィジェットの配置
        button_top.pack()
        button_center1.pack(expand = True)
        button_center2.pack(expand = True)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

これも占有領域を書いてみます。

 

fill

fillは、これまで説明してきた占有領域に対して、ウィジェットの幅、高さ、もしくは両方を合わせます。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_top = tk.Button(self.master, text = "TOP", width = 8)
        button_center = tk.Button(self.master, text = "CENTER", width = 8)

        # ウィジェットの配置
        button_top.pack()
        button_center.pack(expand = True, fill = tk.X)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

fill = tk.Y のとき

fill = tk.BOTH

 

ipadx, ipady

ウィジェットの内側の隙間の量を指定します。

ipadxが横方向、ipadyが縦方向の隙間となります。

隙間を指定することで、ウィジェットの大きさも大きくなります。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button_ipad0 = tk.Button(self.master, text = "ipadx = 0\nipady = 0")
        button_ipad  = tk.Button(self.master, text = "ipadx = 30\nipady = 10")

        # ウィジェットの配置
        button_ipad0.pack()
        button_ipad.pack(ipadx = 30, ipady = 10)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

padx, pady

ウィジェットの外側の隙間の量を指定します。

padxが横方向、padyが縦方向の隙間となります。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button1 = tk.Button(self.master, text = "Button1")
        button2 = tk.Button(self.master, text = "Button2")
        button3 = tk.Button(self.master, text = "Button3")
        button4 = tk.Button(self.master, text = "Button4")
        button_pad  = tk.Button(self.master, text = "padx = 30\npady = 10")

        # ウィジェットの配置
        button1.pack(side = tk.TOP, expand = True, fill = tk.BOTH)
        button4.pack(side = tk.BOTTOM, expand = True, fill = tk.BOTH)
        button2.pack(side = tk.LEFT, expand = True, fill = tk.BOTH)
        button_pad.pack(side = tk.LEFT, padx = 30, pady = 10)
        button3.pack(side = tk.LEFT, expand = True, fill = tk.BOTH)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

after, before

ウィジェットの配置は順番が大事と説明してきましたが、すでに配置されているウィジェットの間に挿入して配置する場合に用います。

afterは指定したウィジェットの次にウィジェットを配置します。

beforeは指定したウィジェットの前にウィジェットを配置します。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # ボタンの作成
        button1 = tk.Button(self.master, text = "Button1")
        button2 = tk.Button(self.master, text = "Button2")
        button3 = tk.Button(self.master, text = "Button3")
        button4 = tk.Button(self.master, text = "Button4")
        button5 = tk.Button(self.master, text = "Button5")

        button2_after = tk.Button(self.master, text = "Button2_After")
        button5_before = tk.Button(self.master, text = "Button5_Before")


        # ウィジェットの配置
        button1.pack()
        button2.pack()
        button3.pack()
        button4.pack()
        button5.pack()
        # すでに配置されているウィジェットの次に配置する
        button2_after.pack(after = button2)
        # すでに配置されているウィジェットの前に配置する
        button5_before.pack(before = button5)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

in_

ウィジェット作成時に親ウィジェットを指定せずに、配置時(pack時)に親ウィジェットを指定します。

(サンプル)

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.geometry("250x250") 

        # 左側のフレーム
        frame_left = tk.Frame(self.master)
        # 右側のフレーム
        frame_right = tk.Frame(self.master)

        # ボタンの作成
        button1 = tk.Button(frame_left, text = "Button1")
        button2 = tk.Button(text = "Button2") # ここでは親のウィジェットを指定していない

        # ウィジェットの配置
        button1.pack()
        button2.pack(in_ = frame_right) # ここでは親のウィジェットを指定

        # フレームの配置
        frame_left.pack(side = tk.LEFT, expand = True)
        frame_right.pack(side = tk.LEFT, expand = True)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

まとめ

ここまで、ウィジェットの配置は順番が重要だと説明してきましたが、実際には1つの親ウィジェットに、様々なオプションを駆使してウィジェットを配置するのは、かなり困難です。

そのため、いくつかのフレーム(Frame)を使って大枠を作成し、各フレームにウィジェットを配置すると比較的簡単に配置できます。

そこで、私がC#では良く作っていたウィンドウのレイアウトを、フレームをいくつか使いサンプルを作成してみました。

(サンプルプログラム)

import tkinter as tk
from tkinter import filedialog
import os


class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        # ウィンドウタイトル
        self.master.title("ウィジェット配置サンプル(packを使用)")

        self.master.geometry("500x300") 

        # メニューの作成
        self.create_menu()
        # ツールバーの作成
        self.create_tool_bar()
        # ステータスバーの作成
        self.create_status_bar()
        # サイドパネル
        self.create_side_panel()

        # 残りの領域にキャンバスを作成
        canvas = tk.Canvas(self.master, background="#008080")
        canvas.pack(expand=True,  fill=tk.BOTH)

    def create_menu(self):
        ''' メニューの作成'''
        menu_bar = tk.Menu(self)
 
        file_menu = tk.Menu(menu_bar, tearoff = tk.OFF)
        menu_bar.add_cascade(label="ファイル", menu = file_menu) 

        file_menu.add_command(label = "開く", command = self.menu_open_click, accelerator = "Ctrl+O")
        file_menu.add_separator() # セパレータ
        file_menu.add_command(label = "終了", command = self.master.destroy)
        # ショートカットの設定
        menu_bar.bind_all("", self.menu_open_click)

        # 親のメニューに設定
        self.master.config(menu = menu_bar)

    def menu_open_click(self, event=None):
        ''' ファイルを開く'''

        # ファイルを開くダイアログ
        filename = tk.filedialog.askopenfilename(
            initialdir = os.getcwd() # カレントディレクトリ
            )
        print(filename)

    def create_tool_bar(self):
        ''' ツールバー'''

        frame_tool_bar = tk.Frame(self.master, borderwidth = 2, relief = tk.SUNKEN)

        button1 = tk.Button(frame_tool_bar, text = "1", width = 2)
        button2 = tk.Button(frame_tool_bar, text = "2", width = 2)
        button3 = tk.Button(frame_tool_bar, text = "3", width = 2)

        button1.pack(side = tk.LEFT)
        button2.pack(side = tk.LEFT)
        button3.pack(side = tk.LEFT)

        frame_tool_bar.pack(fill = tk.X)

    def create_status_bar(self):
        '''ステータスバー'''
        frame_status_bar = tk.Frame(self.master, borderwidth = 2, relief = tk.SUNKEN)

        self.label1 = tk.Label(frame_status_bar, text = "ステータスラベル1")
        self.label2 = tk.Label(frame_status_bar, text = "ステータスラベル2")

        self.label1.pack(side = tk.LEFT)
        self.label2.pack(side = tk.RIGHT)

        frame_status_bar.pack(side = tk.BOTTOM, fill = tk.X)

    def create_side_panel(self):
        '''サイドパネル'''
        side_panel = tk.Frame(self.master, borderwidth = 2, relief = tk.SUNKEN)

        button1 = tk.Button(side_panel, text = "ボタン1", width = 15)
        button2 = tk.Button(side_panel, text = "ボタン2", width = 15)

        button1.pack()
        button2.pack()

        side_panel.pack(side = tk.RIGHT, fill = tk.Y)


if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

【Python/tkinter】Button(ボタン)

tkinterでボタンの作成のサンプルを以下に示します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.title("ボタンの作成")     # ウィンドウタイトル
        self.master.geometry("300x100")       # ウィンドウサイズ(幅x高さ)

        #--------------------------------------------------------
        # ボタンの作成
        button = tk.Button(self.master, 
                           text = "ボタン",             # ボタンの表示名
                           command = self.button_click  # クリックされたときに呼ばれるメソッド
                           )
        button.pack()
        #--------------------------------------------------------
    def button_click(self):
        '''クリックされたときに呼ばれるメソッド'''
        print("ボタンがクリックされた")

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行画面)

構文

ボタンオブジェクト = tk.Button(親ウィジェット, オプション1 = 設定値, オプション2 = 設定値,・・・)

オプション

オプション名 説明
activebackground クリックされたときの背景色を指定します。
activeforeground クリックされたときの文字色を指定します。
anchor 文字の配置位置を指定します。
【設定値】tk.N, tk.S, tk.W, tk.E, tk.NW, tk.NE, tk.SW, tk.SE, tk.CENTER
background 背景色を指定します。
bd 枠線の太さを指定します。
bg 通常時の背景色を指定します。
bitmap モノクロのBitmapを指定します。
(参考)https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/bitmaps.html
borderwidth bdと同じ
command ボタンがクリックされたときに呼び出すメソッドの名前を指定します。
compound 文字と画像の両方を表示する際に、文字に対して画像の表示位置を指定します。
【設定値】tk.LEFT, tk.RIGHT, tk.BOTTOM, tk.TOP, tk.CENTER
cursor ウィジェット上にマウスポインタがある際のカーソルの種類を指定します。
(参考)https://tkdocs.com/shipman/cursors.html
default
disabledforeground stateオプションで無効(DISABLED)に設定している際の文字色を設定します。
fg 表示する文字色を指定します。(foregroundと同じ)
font 表示する文字のフォントを指定します。
foreground
height ボタンの高さを文字数で指定します。
画像を配置した時は、画素数の指定になります。
highlightbackground
highlightcolor
highlightthickness
image 表示する画像を指定します。
justify 複数行の文字のときの、文字寄せ方向を指定します。
【設定値】左寄せ(tk.LEFT), 中央寄せ(tk.CENTER), 右寄せ(tk.RIGHT)
overrelief
padx 文字の両側の隙間を指定します。
pady 文字の上下の隙間を指定します。
relief ボタンのスタイルを指定します。
【設定値】tk.RAISED, tk.GROOVE, tk.SUNKEN, tk.RIDGE, tk.FLAT
repeatdelay
repeatinterval
state
takefocus
text 表示する文字を指定します。
textvariable StringVarクラスオブジェクトを指定し、ボタンの文字列を指定します。
underline 指定した順番(先頭から0始まり)の文字にアンダーラインを付加します。
width ボタンの幅を文字数で指定します。
wraplength 文字の折り返し幅を指定します。

 

サンプルプログラム

評価に用いたプログラムを以下に示します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.title("ボタンの作成(Windowsスタイル)")     # ウィンドウタイトル
        self.master.geometry("580x580")       # ウィンドウサイズ(幅x高さ)

        # ボタンの作成
        button1 = tk.Button(self.master, text = "ボタン")
        # クリックイベントの指定
        button2 = tk.Button(self.master, text = "クリック", 
                            command = self.button_click # クリック時に呼び出されるメソッド名
                            )
        # 無効ボタン
        button3 = tk.Button(self.master, text = "無効ボタン",
                            state = tk.DISABLED # 無効:tk.DISABLED 有効:tk.NORMAL
                            )
        # ボタンサイズ
        button4 = tk.Button(self.master, text = "ボタンサイズ", 
                            width = 20, height = 2      # サイズは文字数で指定
                            )
        # フォントサイズ
        button5 = tk.Button(self.master, text = "フォントサイズ", 
                            font = ("", 18) # フォントサイズの変更
                            )
        # ボタンスタイル
        button6 = tk.Button(self.master, text = "RAISED", 
                            relief = tk.RAISED      
                            )
        button7 = tk.Button(self.master, text = "GROOVE", 
                            relief = tk.GROOVE      
                            )
        button8 = tk.Button(self.master, text = "SUNKEN", 
                            relief = tk.SUNKEN      # 凹んだ状態(クリックはできる)
                            )
        button9 = tk.Button(self.master, text = "RIDGE", 
                            relief = tk.RIDGE      
                            )
        button10 = tk.Button(self.master, text = "FLAT", 
                            relief = tk.RIDGE      
                            )

        # 文字の位置
        button11 = tk.Button(self.master, text = "NW", 
                            width = 10, height = 2,
                            anchor = tk.NW 
                            )
        button12 = tk.Button(self.master, text = "N", 
                            width = 10, height = 2,
                            anchor = tk.N
                            )
        button13 = tk.Button(self.master, text = "NE", 
                            width = 10, height = 2,
                            anchor = tk.NE
                            )
        button14 = tk.Button(self.master, text = "W", 
                            width = 10, height = 2,
                            anchor = tk.W
                            )
        button15 = tk.Button(self.master, text = "CENTER", 
                            width = 10, height = 2,
                            anchor = tk.CENTER
                            )
        button16 = tk.Button(self.master, text = "E", 
                            width = 10, height = 2,
                            anchor = tk.E
                            )
        button17 = tk.Button(self.master, text = "SW", 
                            width = 10, height = 2,
                            anchor = tk.SW
                            )
        button18 = tk.Button(self.master, text = "S", 
                            width = 10, height = 2,
                            anchor = tk.S
                            )
        button19 = tk.Button(self.master, text = "SE", 
                            width = 10, height = 2,
                            anchor = tk.SE
                            )

        # 文字の左寄せ
        button20 = tk.Button(self.master, text = "o文字左寄せo\noo文字左寄せoo\nooo文字左寄せooo", 
                            width = 25, height = 3,
                            justify = tk.LEFT
                            )       
        
        # 文字の中央寄せ
        button21 = tk.Button(self.master, text = "o文字中央寄せo\noo文字中央寄せoo\nooo文字中央寄せooo", 
                            width = 25, height = 3,
                            justify = tk.CENTER
                            )

        # 文字の右寄せ
        button22 = tk.Button(self.master, text = "o文字右寄せo\noo文字右寄せoo\nooo文字右寄せooo", 
                            width = 25, height = 3,
                            justify = tk.RIGHT
                            )

        # 枠線幅
        button23 = tk.Button(self.master, text = "枠線幅2", 
                            bd = 2
                            )
        button24 = tk.Button(self.master, text = "枠線幅4", 
                            bd = 4
                            )
        button25 = tk.Button(self.master, text = "枠線幅6", 
                            bd = 6
                            )
        # 横方向のパディング(文字列の両側の隙間)
        button26 = tk.Button(self.master, text = "padx=2", 
                            padx = 2
                            )
        button27 = tk.Button(self.master, text = "padx=10", 
                            padx = 10
                            )
        button28 = tk.Button(self.master, text = "padx=20", 
                            padx = 20
                            )
        # 縦方向のパディング(文字列の上下の隙間)
        button29 = tk.Button(self.master, text = "pady=2", 
                            pady = 2
                            )
        button30 = tk.Button(self.master, text = "pady=10", 
                            pady = 10
                            )
        button31 = tk.Button(self.master, text = "pady=20", 
                            pady = 20
                            )
        # 横、縦方向のパディング組み合わせ
        button32 = tk.Button(self.master, text = "padx=20\npady=10", 
                            padx = 20, pady = 10
                            )
        # wraplength
        button33 = tk.Button(self.master, text = "wraplength文字の折り返し幅", 
                            wraplength = 60
                            )

        # 色の変更
        button34 = tk.Button(self.master, text = "色の変更", 
                            bg = "#00ff00", # 通常時の背景色
                            fg = "#ff00ff", # 通常時の文字色
                            activebackground = "#ff0000", # クリックされた時の背景色
                            activeforeground = "#0000ff"  # クリックされた時の文字色
                            )
        # ハイライトカラー
        button35 = tk.Button(self.master, text = "ハイライトカラー",  # 無効?
                            highlightcolor = "#ffff00" # ハイライトカラー
                            )
        # アンダーライン(1文字)
        button36 = tk.Button(self.master, text = "アンダーライン(1文字)", 
                            underline = 2      # 2番目(0始まり)の文字にアンダーライン、-1で無し
                            ) 
        # アンダーライン(全文字)
        button37 = tk.Button(self.master, text = "アンダーライン(全文字)", 
                            font = ("", 9, "underline")      # 文字全体のアンダーラインはfontで指定
                            ) 

        # ボタンの配置
        button1.grid(row=0, column=0)
        button2.grid(row=0, column=1)
        button3.grid(row=0, column=2)

        button4.grid(row=1, column=0)
        button5.grid(row=1, column=1)

        button6.grid(row=2, column=0)
        button7.grid(row=2, column=1)
        button8.grid(row=2, column=2)
        button9.grid(row=3, column=0)
        button10.grid(row=3, column=1)

        button11.grid(row=4, column=0)
        button12.grid(row=4, column=1)
        button13.grid(row=4, column=2)
        button14.grid(row=5, column=0)
        button15.grid(row=5, column=1)
        button16.grid(row=5, column=2)
        button17.grid(row=6, column=0)
        button18.grid(row=6, column=1)
        button19.grid(row=6, column=2)

        button20.grid(row=7, column=0)
        button21.grid(row=7, column=1)
        button22.grid(row=7, column=2)

        button23.grid(row=8, column=0)
        button24.grid(row=8, column=1)
        button25.grid(row=8, column=2)

        button26.grid(row=9, column=0)
        button27.grid(row=9, column=1)
        button28.grid(row=9, column=2)

        button29.grid(row=10, column=0)
        button30.grid(row=10, column=1)
        button31.grid(row=10, column=2)
        button32.grid(row=11, column=0)

        button33.grid(row=12, column=0)
        button34.grid(row=12, column=1)
        button35.grid(row=12, column=2)

        button36.grid(row=13, column=0)
        button37.grid(row=13, column=1)

    def button_click(self):
        print("ボタンがクリックされた")

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

【Python/tkinter】ウィンドウの作成

tkinterでは、クラスを用いた書き方と、用いない書き方がありますが、クラスを用いたウィンドウ作成のための最小限のコードを示します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

上記コードを実行すると以下のようなウィンドウが表示されます。

(実行結果)

 

もう少し肉付けをして、ウィンドウのタイトルと表示されるウィンドウのサイズを指定します。

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master = None):
        super().__init__(master)

        self.master.title("タイトル")    # ウィンドウタイトル
        self.master.geometry("400x300") # ウィンドウサイズ(幅x高さ)

if __name__ == "__main__":
    root = tk.Tk()
    app = Application(master = root)
    app.mainloop()

(実行結果)

 

geometryで指定したサイズは、ウィンドウのタイトルーバー付のサイズではなく、ウィンドウの内側のサイズとなります。

【Python】リストの作成、追加、削除、挿入など

C#では、配列とリストは明確に別物なのですが、Pythonでは配列と言いながらリストの事を指している場合が多いようです。

Pythonには型宣言が無いので、C#で言うところのobjectクラスのリスト(List<object>)にイメージが近く、各要素には、数値や文字列などの、ごちゃまぜもできます。

以下のコード例は、上から順に実行した場合です。

リストの宣言

角カッコ([])で変数がリストである事を宣言します。

list_data = []

リストの初期化

角カッコ([])の中に要素をカンマ(,)で区切って初期化します。
各要素の型はごちゃまぜにできます。

list_data = [0, "abc", 2, 3, "def", 4]
print(list_data)

実行結果

[0, ‘abc’, 2, 3, ‘def’, 4]

要素の追加

append(追加する要素)で、リストの最後に要素が追加されます。

list_data.append(5)
print(list_data)

実行結果

[0, ‘abc’, 2, 3, ‘def’, 4, 5]

リストにリストを追加

元のリスト.extend(追加するリスト)で、元のリストに別のリストを追加し、追加されたリストは元のリストに格納されます

list_data = [0, 'abc', 2, 3, 'def', 4, 5]
list_ext  = ['ghi', 6, 7, 8, 9, 10, 11, 12]
list_data.extend(list_ext)
print(list_data)

実行結果

[0, ‘abc’, 2, 3, ‘def’, 4, 5, ‘ghi’, 6, 7, 8, 9, 10, 11, 12]

指定した要素のindex番号を取得

index(番号を取得する要素)で、要素のindex番号を取得します。
指定した要素が複数ある場合は、最初に見つけた要素のindex番号を取得します。

print(list_data.index('ghi'))

実行結果

7

要素の番号を指定して削除

del リスト[削除するindex番号]で、要素を削除します。

del list_data[list_data.index('ghi')]
print(list_data)

実行結果

[0, ‘abc’, 2, 3, ‘def’, 4, 5, 6, 7, 8, 9, 10, 11, 12]

要素の番号を指定して要素を抜き出す(削除する)

pop(削除する要素のindex番号)で、要素を削除し、削除した要素を返します。

ret = list_data.pop(1)
print(ret)
print(list_data)

実行結果

abc

[0, 2, 3, ‘def’, 4, 5]

要素を指定して削除

remove(削除する要素)で、要素を削除します。
指定した要素が複数ある場合は、最初に見つけた要素を削除します。

list_data.remove("def")
print(list_data)

実行結果

[0, 2, 3, 4, 5]

要素の挿入

insert(挿入する場所のindex番号, 挿入する要素)で、要素を挿入します。

list_data.insert(1, 10)
print(list_data)

実行結果

[0, 10, 2, 3, 4, 5]

要素があるかどうか?

要素 in リストで、要素があれば True、なければ Falseが返ります。

print(10 in list_data)
print(11 in list_data)

実行結果

True
False

要素のindex番号を取得

index(番号を取得する要素)で、要素のindex番号を取得します。
指定した要素が複数ある場合は、最初に見つけた要素のindex番号を取得します。

print(list_data.index(10))

実行結果

1

リストの要素数を取得

len(リスト)で、要素の個数を取得します。

print(len(list_data))

実行結果

6

指定した要素の個数を取得

count(要素)で、リスト中の要素の個数を取得します。

list_data = [0, 1, "abc, 2, 3, "abc", 4, 5]
print(list_data.count("abc"))

実行結果

2

 

【Python】数値演算

Pythonにおいて、足し算、引き算、掛け算、割り算などの数値演算は、以下のようになります。

 

演算の種類 演算子 計算例 答え
足し算 + 2 + 3 5
引き算 7 – 4 3
掛け算 * 3 * 6 18
割り算 / 7 / 2 3.5
商(小数以下切り捨て) // 7 // 2 3
余り % 7 % 2 1
べき乗 ** 2 ** 8 256

 

特に、割り算は整数で割っても答えが小数で返されるのは、他のC言語やC#の仕様とは異なるので、注意が必要です。切り捨ての演算(//)も覚えておきたいところですね。

 

画像処理の場合、4の倍数の計算とかもよくやっているのですが、以下のような計算になります。

(計算例)638を超える4の倍数の値の計算

>>> (638 + 3) // 4 * 4
640

【Python】importとは?

Pythonを勉強し始めると、いきなり

import numpy as np

とかが出てきて、ナニコレ?ってなるのですが、C言語で言うところのヘッダファイル(*.h)のインクルードにイメージが近いと思います。

Pythonでは、import とすることでモジュール(ライブラリ)を使用できるようにしています。

 

書式的には

import 「モジュール名 もしくは Pythonファイル名の拡張子なし」 as 「代替名」

となります。

 

そのため、最初のプログラム例では、numpyモジュールを np として用いる宣言をしています。

(使用例)

import numpy as np

data = np.array([0,1,2])
print(data)

as以降の代替名の部分は無くても構いません。

import numpy

data = numpy.array([0,1,2])
print(data)

また、これとは別に、似た感じで

from matplotlib import pyplot

というのも登場しますが、この書式的には

from 「モジュール名」 import 「クラス名 もしくは 関数名」

となります。

そのため、上記の例では、 matplotlibモジュールの中からpyplotだけを用いる事を宣言しています。

【Python】Visual Studioのインデントを自動に設定する

Visual StudioでPythonのプログラムを書くとき、for文やif文など、インデントが必要な場合、改行しても自動でインデントしてくれないので、自動でインデントするための設定を行います。

 

設定方法は、Visual Studioのメニューから、ツール→オプションでオプション設定画面を開きます。

 

 

オプション画面の テキストエディター → Python → タブ を選択し、インデントスマート を選択し、OKボタンをクリックします。

これで、自動でインデントしてくれます。

C#erによるPython学習、C#とPythonの違い

2021年現在、仕事では 「C# + C言語のDLL」の開発がほとんどで、Pythonを使う機会が無いのですが、さすがに Python を勉強するか?と思っています。

しかし、C#脳でPythonを勉強していると、なんで、こうするの?と思う事がよくあります。

でも、私がVB6.0から→(C++/CLI)→C#に乗り換えた時もC#の何がいいの?とか思ってましたが、今はC#最高!になってます。(C++/CLIはやらなきゃ良かった。。)

Python最高!になる日は来るのだろうか??


(2021.5.22追記)

Pythonを集中的に勉強しだしてから半年たちましたが、ようやくPythonでもいいかも?と思えるようになってきました。最初の1か月ぐらいはPythonが嫌でしょうがなかったですけどねww

開発環境もVisual Studio2019であれば、デバッグなどはC#と同じようにステップ実行やウォッチなども使えるので便利です。Visual Studio Codeも使ってみましたが、コーディングはVS Codeの方がやりやすいように感じましたが、デバッグは慣れもあって、Visual Studioの方が良かったです。

Visual Studio2015も使いましたが、Pythonの環境を構築するのが難しくて断念しました。

Pythonを始めてモヤモヤポイントがGUIをどうするの?というのがあったのですが、tkinterを使うとC#と同じようなGUIを作る事ができます。

Pythonは処理時間が遅くない?という思いもありましたが、OpenCVやnumpyなどを使えば処理が遅い事は無いですし、C#でやっていた時のように重たい処理はC言語ライブラリを作成し、DllImportで関数を呼んでいたのと同じ様に、Pythonではctypesというモジュールを使うと、C言語ライブラリの関数を呼ぶ事が可能になります。

あとは、Pythonではフリーで使えるライブラリが圧倒的に多いので、目的に合ったライブラリが見つかれば、開発時間の短縮にもつながると思います。


 

以下は、C#から見たときのPythonの違いを書いています。

 

構文的な違い

  • 終端文字(;)が無い
  • if文やfor文などの中カッコ({})が無い代わりに、行の最後にコロン(:)を付けてインデントを揃える
  • クラスのNewがない。
    Newが無いので関数を呼んでいるのか?クラスをインスタンスしているのか?分かりづらい
  • クラスにprivate/publicが無い。基本、publicだが代替手法がある
  • オーバーロードがない。→デフォルト引数で代替できるところまで。
  • ラベルやボタンなどのC#で言うところのコントロールはPythonでは ウィジェット(widget)という
  • 特殊メソッドなるものがある

型宣言がない

int a = 123;
string b = "abc";
a = 123
b = "abc"

型が無いのに型違いでエラーになる事もあり、なかなか慣れません。。
とくに関数に変数を渡す時がわかりずらい。
型を調べるには type()関数を使うとできます。

a = 100
b = "abc"

print(type(a))
print(type(b))

# 型が XX かどうか?
if (type(a) is int):
  print("int型です")
elif (type(a) is float):
  print("float型です")
elif (type(a) is str):
  print("str型です")
else:
  print("その他の型です")

実行結果

<class ‘int’>

<class ‘str’>

int型です

型は、全てがC#でいうところのobject型に近い

 

行のコメント

// 一行のコメント
# 一行のコメント

行の先頭にシャープ(#)を付けます。

 

複数行のコメント

/*
複数行の
コメント
*/
"""
複数行の
コメント
"""

シングルクォーテーション(‘)を3つ(”’)もしくは ダブルクォーテーション(“)を3つ(”””‘)でコメントにしたい部分を囲います。

 

関数のコメント

/// <summary>
/// aとbを足す
/// </summary>
/// <param name="a">足す値a</param>
/// <param name="b">足す値b</param>
/// <returns></returns>
private static int Add(int a, int b)
{
    return a + b;
}

C#では、関数の上の行でスラッシュ(/)を3つ(///)書くと、XMLコメントのフォーマットが表示されるので、そこにコメントを記載します。

def add(a, b):
  """
  [概要]
  aとbを足したものを返す
  [パラメータ]
  a : 足す値a
  b : 足す値b
  [注釈]
  aとbは同じ型のこと
  """
  return a + b

関数名の行の下にインデントして、シングルクォーテーション(‘)を3つ(”’)もしくは ダブルクォーテーション(“)を3つ(”””‘)でコメントにしたい部分を囲います。

一般的なコメントの定型は分からないのですが、上記プログラムのように記載すると、開発環境によって、以下のように関数の説明が表示されます。

 

インクリメント/デクリメント

int i = 0;
i++;  // インクリメント
i--;  // デクリメント
i = 0
i += 1  # インクリメント
i -= 1  # デクリメント

値の代入は参照渡し?

まずは下記のサンプルをご覧ください。

a = 100
print(id(a))
a = 200
print(id(a))
b = a
print(id(b))

実行結果

10917664

10920864

10920864

id()関数はポインタ?みたいなのを取得できる関数がすが、上記の例では a に値を入れるたびに id が変わっています。さらに b に a を代入すると、a と b の id は等しくなります。

ただし、C#の参照渡し/値渡しの感覚とは少し異なるので注意が必要です。
どちらかというと、ポインタの値渡し(アドレスの値を渡す)と言った方が近いかもしれません。

 

まとめ

C#とPythonの違いは、当然ながら他にもたくさんありますが、個別にまとめたいと思います。

PythonはC#と比べて、処理は遅そうだし、画像の表示(フレームレート)も遅そうだし、GUIプログラムを作るのも大変そう。。と不安に思いながら勉強していてます。

Pythonの場合、処理をベタに書いている(クラスではない)例の紹介が多く、さらに、ほとんどがCUI(Character-based User Interface)なので、クラスでGUIなC#に慣れていると、どうしても抵抗があったのですが、GUIモジュールのTkinterをクラスで書き始めると、少しPythonの抵抗が薄れ始めています。

【Python】おすすめの開発環境は?

Pythonの始めるには、まずは開発環境を整える必要がありますが、Googleで調べると、いろいろと言葉が出てきて、何が何だか分からなくなります。(って、私はそうでした。)

 

Anaconda、Jupyter Notebook、Visual Source Code、PyCharmなどなど。。

 

Anacondaそのものが開発環境?とか思っていたレベルから始めたので、最初は大変でした。。

人によっても、おすすめしている開発環境が異なるので、何を信じたらいいか?分からなくなりますね。

おそらくは、人によって、Pythonをやる前の開発環境(OSや使用言語)が異なるために、おすすめも違ってくるのだと思いますが、WindowsでC#を使って開発をしていた身としては、以下の2つがおすすめ出来ると思っています。

 

Google Colaboratory

初めてPythonを触るなら、GoogleのColaboratoryがおすすめです。

 

Colaboratoryのページ(https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja)にアクセスさえすれば、開発環境のインストールなしに、Pythonプログラムを組む事が可能になります。

 

下の画像は、私がPythonを勉強する時に使っていた画面ですが、Pythonのコードとテキストを入れ込めるので、注意点などをテキストで書きながら、動作を確認してPythonを勉強しています。

自分なりのテキストを作るつもりで、Pythonの動作を確かめていくと、後から見直せるので、便利だと思います。

さらに、ファイルがクラウド上にあるので、会社や自宅など、場所、PCを問わず、見る事ができるのも助かります。

 

オプションで、犬とか猫を表示出来るのも、ちょっとかわいい。。

 

まず最初は、このページ↓がおススメです。

https://www.python.jp/train/index.html

 

Visual Studio

ColaboratoryでPythonをある程度、覚えて、アプリを作りたくなったら、Visual Studio がおすすめだと思います。

 

それは私がC#をやっていたからという理由もありますが、プログラムのデバッグをするときに、やっぱりステップ実行をしながら変数の値をウォッチを使いながら確認したり、関数の定義へ行ったり/戻ったり、ステップインなどをしたくなる訳です。

そうしたら、やっぱり使い慣れている Visual Studio が一番便利に感じます。

 

 

また、Visual Studio 2017以降では、Pythonの開発環境というウィンドウがあり、Pythonのバージョンごとに各種ライブラリが簡単に切り替えられるようになっており、ライブラリのインストール、更新、削除が非常に簡単です。(Visual Studio2015にもPython環境のウィンドウがありますが、使いにくいです。)

 

まとめ

今回は、Pythonの開発環境として、Googleの Colaboratory と Visual Studio がおすすめと言っていますが、私自身も、まだPythonの開発経験が浅いので、結局のところ本当に何がいいのか?もやもやしている部分もありますが、C#の次にPythonをやる分には、上の2つが入りやすかったです。

また、Pythonにはさまざまなモジュール(ライブライ)があって、何からやったらいいの?という疑問もあったのですが、私の場合、Visual Studioで、ウィンドウGUI用モジュールのtkinterを勉強し始めてから、理解が進んだ気がします。

https://imagingsolution.net/tag/tkinter/

【Python,matplotlib】動くグラフをAnimationGifに保存する方法

matplotlibで動くグラフを書いて、AnimationGifに保存するにはImageMagickという画像のソフトをmatplotlibから呼び出すように設定すれば、こんな風な動くグラフが作成できます。

 

まずはImageMagickの入手から。

ImageMagickは下記ページより、ダウンロードします。

http://www.imagemagick.org/script/download.php

 

Windows版のファイルは下の方にあるので、downloadをクリックしてファイル(ImageMagick-7.0.6-0-Q16-x64-dll.exe)を入手します。

 

ImageMagickのインストールはダウンロードしたファイルを実行し、基本デフォルトのままのインストールで大丈夫だと思います。

 

ImageMagickのインストールが出来たら、matplotlibの設定を行います。

 

まず、matplotlibのmatplotlibrcというファイルがある場所を確認します。

場所はPythonのプログラムで

 

import matplotlib
print(matplotlib.matplotlib_fname())

 

と入力し実行すると、matplotlibrcのファイルのパスが表示されるので、matplotlibrcファイルをメモ帳などのテキストエディタで開きます。

 

私の場合のパスは

C:\Program Files\Anaconda3\Lib\site-packages\matplotlib\mpl-data\matplotlibrc

でした。

 

このmatplotlibrcファイルの一番下の方に

 

#animation.convert_path: ‘convert’ #・・・・・・

と書いてある部分があるので、これを編集してもいいのですが、私は↓のようにImageMagickの実行ファイル(magick.exe)のパスを追記しました。

 

この状態で、このようなコード↓を書くと、最初に示したアニメーションGifのファイルが生成されます。

 

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()
x = np.arange(-np.pi, np.pi, 0.1)

ims = []
for a in range(40):
    y = np.sin(x - a / 20 *  np.pi)
    # sinカーブ
    im1, = plt.plot(x, y, "b")
    # 点
    im2, = plt.plot(-np.pi, np.sin(-np.pi - a / 20 *  np.pi), marker='o', color='b' )

    ims.append([im1, im2])

ani = animation.ArtistAnimation(fig, ims, interval=33)
ani.save('sample.gif', writer='imagemagick')

 

Sinカーブだけのサンプルは探せばいっぱいあるのですが、線上に点を打つだけでも、訳わかんなかった~(まだ、分かってないですけど。。)

PythonをVisual Studioでインストールする方法

PythonはこれまでAnacondaをインストールしてJupyter NotebookからPythonのプログラムを書いていたのですが、今までプログラムといえばIDEはVisual Studioを使っていた身としては、お手軽にステップ実行ができるJupyter Notebookは良いといえばいいのですが、インテリセンスが使えないのは、ものすごくつらい。。

 

ということで、Visual StudioからPythonを使えるように、Visual StudioへPythonをインストールしました。

 

まず、私の環境は

●Windows10(64bit)

●Visual Studio Community 2017

です。

 

Visual Studio 2017では、後から簡単にPythonなどのオプションを追加できるようになっているので、Visual Studio 2017をインストールした後からのPythonのインストール方法です。

 

まずは、スタートメニューからVisual Studio Installerを起動します。

 

Visual Studio Installerが起動したら、Visual Studio Community 2017 の変更をクリックします。

 

Python開発の右上のチェックを入れ、オプションを選択します。

実際にどれが必要か?詳しくはわかっていないのですが、とりあえずはこの↓設定にしました。

 

オプションのチェックを入れたら、変更をクリックします。

すると、Pythonのインストールが始まります。

 

これで、インストールは完了なので、実際にPythonを起動してみます。

ファイルメニューのファイル→新規作成→プロジェクトと選択し

 

テンプレートの中からPythonを選択し、Pythonアプリケーションを選択し、名前、場所、ソリューション名は適当に指定して、OKボタンをクリックします。

 

すると、こんな画面が開きます。

 

Python環境のウィンドウが表示されていない場合は、Visual Studioのメニューより、表示→その他ウィンドウ→Python環境と選択し、Python環境のウィンドウを表示してください。

このウィンドウはnumpyやpillowなどの各種モジュールをPythonのバージョンごとに管理するウィンドウで、モジュールインストールなどを簡単に行う事が可能になります。ただし、Visual Studio2017以降がおすすめです。

次に、使用するPythonの環境(バージョン)を選択し、概要の部分をクリックし、パッケージ(PyPI)を選択します。

すると、Python環境ごとにインストールされているモジュール一覧が表示されます。

もし、必要なモジュールが表示されていない(インストールされていない)場合は、PyPIとインストールされたパッケージの検索の部分にモジュールの名前を入力すると、XXXのインストールと表示されているので、その部分をクリックするだけで、モジュールがインストールされます。

これでVisual StudioでPython開発環境の構築は完了です。

試しにimportするのにimとキー入力してみると、インテリセンスもちゃんと表示してくれます。

 

さらにこんなコード↓では

 

C#とかと同じようにブレークポイントを置いて、ステップ実行をしてみると、ウォッチの機能もちゃんと動いてくれます。

 

従来のコマンドラインのPythonの入力も対話型ウィンドウを開くの部分をクリックすると

 

このような画面がVisual Studioの下の方にウィンドウが表示されるので、この部分にコードを入力してPythonを実行することもできます。

 

ちなみに、今回はVisual StudioからAnacondaをインストールしたので、スタートメニューからJupyter Notebookの利用も可能です。

 

やっぱりプログラムを組むのには、インテリセンスやステップ実行、ウォッチの機能は欲しいので、しばらくはVisual StudioからPythonをいじろうと思っています。