アナログ時計に目盛りを追加しよう
前回はtkinterを使って、長針、短針、秒針を表示するアナログ時計を作成しました。
今回は前回作ったプログラムに、円と目盛りを追加して表示しましょう。
目盛りを12個追加する
目盛りは1周360度を12等分するので、30度間隔で表示します。
目盛りは直線を使って表示し、外側の座標は円の中心から180ピクセルの位置に置き、内側の座標は外側の座標から10ピクセル内側に設定します。
アナログ時計に目盛りを表示するプログラム
上記のことをふまえて、アナログ時計に目盛りを表示するプログラムです。
円と目盛りは一度描画したらそのままにしたいので、長針、短針、秒針にタグを設定して、針だけを0.2秒単位で再描画しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
### インポート import math import datetime import time import tkinter import threading ### 定数 WIDTH = 400 # 幅 HEIGHT = 400 # 高さ RADIUS = 180 # 半径 NEEDLE_H = 120 # 長針 NEEDLE_M = 160 # 短針 NEEDLE_S = 150 # 秒針 MARK = 10 # 目盛り BASE_AGL = 90 # 基準角度 W_TAG = "needle" # ウィジェットタグ CENTER = int(WIDTH/2),int(HEIGHT/2) ### 時刻取得関数 def get_time(): ### 無限ループ while True: ### 現在時刻取得 now = datetime.datetime.now() ### 角度計算 angle_h = float(BASE_AGL - 30 * now.hour - 0.5 * now.minute) # 時 angle_m = int(BASE_AGL - 6 * now.minute) # 分 angle_s = int(BASE_AGL - 6 * now.second) # 秒 ### 針の終端位置 pos_hx = round(math.cos(math.radians(angle_h))*NEEDLE_H) # 時のX座標 pos_hy = round(math.sin(math.radians(angle_h))*NEEDLE_H) # 時のY座標 pos_mx = round(math.cos(math.radians(angle_m))*NEEDLE_M) # 分のX座標 pos_my = round(math.sin(math.radians(angle_m))*NEEDLE_M) # 分のY座標 pos_sx = round(math.cos(math.radians(angle_s))*NEEDLE_S) # 秒のX座標 pos_sy = round(math.sin(math.radians(angle_s))*NEEDLE_S) # 秒のY座標 ### 秒針表示 canvas.create_line(CENTER, CENTER[0]+pos_hx, CENTER[1]-pos_hy, width=8, tags=W_TAG) canvas.create_line(CENTER, CENTER[0]+pos_mx, CENTER[1]-pos_my, width=5, tags=W_TAG) canvas.create_line(CENTER, CENTER[0]+pos_sx, CENTER[1]-pos_sy, width=2, tags=W_TAG) #### 待ち時間 time.sleep(0.2) ### キャンバス初期化 canvas.delete("needle") ### キャンバス作成 canvas = tkinter.Canvas(master=None, width=WIDTH, height=HEIGHT) ### 円表示 canvas.create_oval(10, 10, 390, 390, outline="lightgray", fill="lightgray") ### 目盛り表示 for mark in range(0, 360, 30): mark_i_x = round(math.cos(math.radians(mark))*(RADIUS-MARK)) # 内側のX座標 mark_i_y = round(math.sin(math.radians(mark))*(RADIUS-MARK)) # 内側のY座標 mark_o_x = round(math.cos(math.radians(mark))*RADIUS) # 外側のX座標 mark_o_y = round(math.sin(math.radians(mark))*RADIUS) # 外側のY座標 canvas.create_line((CENTER[0]+mark_i_x,CENTER[1]+mark_i_y), (CENTER[0]+mark_o_x,CENTER[1]+mark_o_y), width=3, fill="gray") ### キャンバス表示 canvas.pack() ### スレッド作成 thread = threading.Thread(target=get_time, daemon=True) ### スレッド開始 thread.start() ### イベントループ canvas.mainloop() |
プログラムを実行すると、アナログ時計に目盛りが表示されます。