【Python】Tkinterで作るGUIアプリ「個人的よく使うまとめ」

# はじめに
こんにちは。
GUIアプリを作るためにTkinterを使って半年くらい経ちました。
今回はよく使うまとめということで、よく使うコードをこの記事にまとめていきたいと思います。
コードだけ書くと自分的には分かりにくいので、この記事では下記のようなものを作っていきたいと思います。

![まとめ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/1caa81ef-1858-b51c-a92f-63a8c81831aa.gif)


# 環境
- Windows 10 home
- Python 3.7.1


# 大まかな仕様

- 和の計算
    - テキストボックスや、ラベル、ボタンの作成
    
- 日付時刻
    - ライブラリを用いて、日付時刻をテキストで表示
    
- 図形の作成
    - 円や多角形の作成
    
- 図形が動く処理等
    - ループ処理(after()を使う)


# 完成したプログラム

```よく使うまとめ.py
import tkinter as tk
from datetime import datetime

class Circle(): #円オブジェクト
	def __init__(self,canvas,x,y,r,color,tag):
		self.canvas = canvas
		self.x = x #中心のx座標
		self.y = y #中心のy座標
		self.r = r #円の半径
		self.color = color
		self.tag = tag

	def createCircle(self): #円を作るメソッド
		self.canvas.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color,tag=self.tag)
		self.canvas.create_text(self.x,self.y,text=self.tag,font=("Helvetica", 18, "bold"),fill="black",tag=self.tag)

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

		self.width=900
		self.height=400
		self.checkNumber=1

		master.geometry(str(self.width)+"x"+str(self.height)) #ウィンドウの作成

		master.title("よく使うまとめ") #タイトル
		self.master.config(bg="pink") #ウィンドウの背景色

		self.createWidgets() #ウィジェットの作成
		self.createCanvas() #キャンバスの作成

		master.after(50, self.update) #ループ処理

	def createWidgets(self): #ウィジェットの作成
		#「よく使うまとめ」というタイトルのラベル作成
		self.label1 = tk.Label(text="よく使うまとめ",fg="black",bg="cyan",font=("Helvetica",40,"bold"))
		self.label1.place(x=0,y=0)

		#和の計算をするためのテキストボックスやラベル、ボタンの作成
		self.entry1 = tk.Entry(width=15)
		self.entry1.place(x=10,y=120)
		self.entry2 = tk.Entry(width=15)
		self.entry2.place(x=180,y=120)
		self.entry3 = tk.Entry(width=15)
		self.entry3.place(x=350,y=120)

		self.label2 = tk.Label(text="+",fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label2.place(x=128,y=103)
		self.label3 = tk.Label(text="=",fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label3.place(x=298,y=103)

		self.button1 = tk.Button(text="計算する",command=self.button1Click,width=30)
		self.button1.place(x=110, y=180)

	def button1Click(self): #ボタンが押された時に呼ばれるメソッド
		if self.entry1.get() != "" and self.entry2.get() != "":
			self.entry3.delete(0,tk.END)
			self.entry3.insert(0,int(self.entry1.get())+int(self.entry2.get())) #計算結果をentry3に表示

	def createCanvas(self): #キャンバスの作成
		self.canvas = tk.Canvas(self.master,width=self.width/2,height=self.height,bg="blue") #キャンバスの作成
		self.canvas.place(x=self.width/2,y=0)

		self.circle1 = Circle(self.canvas,225,60,50,"red","circle1") #インスタンスcircle1の生成

		#多角形の作成
		self.canvas.create_polygon(10,10,60,10,35,60,fill="purple")
		self.canvas.create_polygon(390,10,440,10,440,60,390,60,fill="orange")
		self.canvas.create_polygon(390,340,440,340,415,390,fill="green")
		self.canvas.create_polygon(10,340,60,340,60,390,10,390,fill="yellow")

	def update(self): #ループ処理
		#円の動きの処理
		self.canvas.delete(self.circle1.tag)
		if self.circle1.y-self.circle1.r <= 0 or self.circle1.y+self.circle1.r >= self.height:
			self.checkNumber*=-1
			if self.circle1.y-self.circle1.r <= 0:
				self.circle1.y+=10
			if self.circle1.y+self.circle1.r >= self.height:
				self.circle1.y-=10
		if self.circle1.y-self.circle1.r > 0 and self.circle1.y+self.circle1.r < self.height:
			if self.checkNumber==1:
				self.circle1.y+=10
			if self.checkNumber==-1:
				self.circle1.y-=10
		self.circle1.createCircle()

		#日付時刻の作成
		self.label4 = tk.Label(text=datetime.now().strftime("%Y/%m/%d %H:%M:%S"),fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label4.place(x=40,y=275)

		self.master.after(50,self.update)

def main():
	win = tk.Tk()
	win.resizable(width=False, height=False) #ウィンドウを固定サイズに
	app = Application(master=win)
	app.mainloop()

if __name__ == "__main__":
	main()
```


# 個々の機能のプログラム

「よく使うまとめ」で作ったアプリの中の機能をそれぞれ分けて実装したものを以下に記していきます。
大まかな仕様で4つに分けた通りにそれぞれ実装していきたいと思います。

## 和の計算

![和の計算.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/38d0c316-16d0-636f-338a-0900d1afb410.gif)



```和の計算.py
import tkinter as tk

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

		self.width=450
		self.height=300

		master.geometry(str(self.width)+"x"+str(self.height)) #ウィンドウの作成

		master.title("和の計算") #タイトル
		self.master.config(bg="pink") #ウィンドウの背景色

		self.createWidgets() #ウィジェットの作成

	def createWidgets(self): #ウィジェットの作成
		#和の計算をするためのテキストボックスやラベル、ボタンの作成
		self.entry1 = tk.Entry(width=15)
		self.entry1.place(x=10,y=120)
		self.entry2 = tk.Entry(width=15)
		self.entry2.place(x=180,y=120)
		self.entry3 = tk.Entry(width=15)
		self.entry3.place(x=350,y=120)

		self.label2 = tk.Label(text="+",fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label2.place(x=128,y=103)
		self.label3 = tk.Label(text="=",fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label3.place(x=298,y=103)

		self.button1 = tk.Button(text="計算する",command=self.button1Click,width=30)
		self.button1.place(x=110, y=180)

	def button1Click(self): #ボタンが押された時に呼ばれるメソッド
		if self.entry1.get() != "" and self.entry2.get() != "":
			self.entry3.delete(0,tk.END)
			self.entry3.insert(0,int(self.entry1.get())+int(self.entry2.get())) #計算結果をentry3に表示

def main():
	win = tk.Tk()
	win.resizable(width=False, height=False) #ウィンドウを固定サイズに
	app = Application(master=win)
	app.mainloop()

if __name__ == "__main__":
	main()
```



## 日付時刻

![日付日時.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/83a2123b-6ec2-e109-cf65-28f3e9c6094e.gif)



```日付時刻.py
import tkinter as tk
from datetime import datetime

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

		self.width=450
		self.height=400

		master.geometry(str(self.width)+"x"+str(self.height)) #ウィンドウの作成

		master.title("日付時刻") #タイトル
		self.master.config(bg="pink") #ウィンドウの背景色

		master.after(50, self.update) #ループ処理

	def update(self): #ループ処理
		#日付時刻の作成
		self.label4 = tk.Label(text=datetime.now().strftime("%Y/%m/%d %H:%M:%S"),fg="black",bg="pink",font=("Helvetica",30,"bold"))
		self.label4.place(x=40,y=175)

		self.master.after(50,self.update)

def main():
	win = tk.Tk()
	win.resizable(width=False, height=False) #ウィンドウを固定サイズに
	app = Application(master=win)
	app.mainloop()

if __name__ == "__main__":
	main()
```



## 図形の作成

<img width="225" alt="図形の作成.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/da658697-0332-b162-a51e-f46047caac51.png">



```図形の作成.py
import tkinter as tk

class Circle(): #円オブジェクト
	def __init__(self,canvas,x,y,r,color,tag):
		self.canvas = canvas
		self.x = x #中心のx座標
		self.y = y #中心のy座標
		self.r = r #円の半径
		self.color = color
		self.tag = tag

	def createCircle(self): #円を作るメソッド
		self.canvas.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color,tag=self.tag)
		self.canvas.create_text(self.x,self.y,text=self.tag,font=("Helvetica", 18, "bold"),fill="black",tag=self.tag)

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

		self.width=450
		self.height=400

		master.geometry(str(self.width)+"x"+str(self.height)) #ウィンドウの作成

		master.title("図形の作成") #タイトル
		#self.master.config(bg="pink") #ウィンドウの背景色

		self.createCanvas() #キャンバスの作成

	def createCanvas(self): #キャンバスの作成
		self.canvas = tk.Canvas(self.master,width=self.width,height=self.height,bg="blue") #キャンバスの作成
		self.canvas.pack()

		self.circle1 = Circle(self.canvas,225,60,50,"red","circle1") #インスタンスcircle1の生成
		self.circle1.createCircle() #円の作成

		#多角形の作成
		self.canvas.create_polygon(10,10,60,10,35,60,fill="purple")
		self.canvas.create_polygon(390,10,440,10,440,60,390,60,fill="orange")
		self.canvas.create_polygon(390,340,440,340,415,390,fill="green")
		self.canvas.create_polygon(10,340,60,340,60,390,10,390,fill="yellow")

def main():
	win = tk.Tk()
	win.resizable(width=False, height=False) #ウィンドウを固定サイズに
	app = Application(master=win)
	app.mainloop()

if __name__ == "__main__":
	main()
```



## 図形が動く処理等

![図形が動く処理等.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309633/ac676af4-6ff8-4b5a-fabf-6319e56e60a2.gif)



```図形が動く処理等.py
import tkinter as tk

class Circle(): #円オブジェクト
	def __init__(self,canvas,x,y,r,color,tag):
		self.canvas = canvas
		self.x = x #中心のx座標
		self.y = y #中心のy座標
		self.r = r #円の半径
		self.color = color
		self.tag = tag

	def createCircle(self): #円を作るメソッド
		self.canvas.create_oval(self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r,fill=self.color,tag=self.tag)
		self.canvas.create_text(self.x,self.y,text=self.tag,font=("Helvetica", 18, "bold"),fill="black",tag=self.tag)

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

		self.width=450
		self.height=400
		self.checkNumber=1

		master.geometry(str(self.width)+"x"+str(self.height)) #ウィンドウの作成

		master.title("よく使うまとめ") #タイトル
		#self.master.config(bg="pink") #ウィンドウの背景色

		self.createCanvas() #キャンバスの作成

		master.after(50, self.update) #ループ処理

	def createCanvas(self): #キャンバスの作成
		self.canvas = tk.Canvas(self.master,width=self.width,height=self.height,bg="blue") #キャンバスの作成
		self.canvas.pack()

		self.circle1 = Circle(self.canvas,225,60,50,"red","circle1") #インスタンスcircle1の生成

	def update(self): #ループ処理
		#円の動きの処理
		self.canvas.delete(self.circle1.tag)
		if self.circle1.y-self.circle1.r <= 0 or self.circle1.y+self.circle1.r >= self.height:
			self.checkNumber*=-1
			if self.circle1.y-self.circle1.r <= 0:
				self.circle1.y+=10
			if self.circle1.y+self.circle1.r >= self.height:
				self.circle1.y-=10
		if self.circle1.y-self.circle1.r > 0 and self.circle1.y+self.circle1.r < self.height:
			if self.checkNumber==1:
				self.circle1.y+=10
			if self.checkNumber==-1:
				self.circle1.y-=10
		self.circle1.createCircle()

		self.master.after(50,self.update)

def main():
	win = tk.Tk()
	win.resizable(width=False, height=False) #ウィンドウを固定サイズに
	app = Application(master=win)
	app.mainloop()

if __name__ == "__main__":
	main()
```




以上で「個人的よく使うまとめ」は完成になります。
ここまで読んでいただき、ありがとうございました。