回答編集履歴

2

afterによるループをwhileに変更

2020/06/24 09:13

投稿

yymmt
yymmt

スコア1615

test CHANGED
@@ -26,17 +26,21 @@
26
26
 
27
27
 
28
28
 
29
+ [追記] teamiklさんの指摘事項(afterでループするとメインスレッドから呼ばれてしまうバグ)を修正しました。
30
+
31
+
32
+
29
33
  ```python
30
34
 
31
35
  import datetime
32
36
 
33
37
  import schedule
34
38
 
35
- import sys
36
-
37
39
  import threading
38
40
 
39
41
  import tkinter as tk
42
+
43
+ import time
40
44
 
41
45
 
42
46
 
@@ -108,13 +112,13 @@
108
112
 
109
113
  def run_monitor(self):
110
114
 
111
- schedule.run_pending()
115
+ while self.running:
112
116
 
113
- if not self.running:
117
+ schedule.run_pending()
114
118
 
115
- sys.exit(1)
119
+ time.sleep(0.2)
116
120
 
117
- self.root.after(200, self.run_monitor)
121
+ self.root.quit()
118
122
 
119
123
 
120
124
 
@@ -164,4 +168,6 @@
164
168
 
165
169
  main()
166
170
 
171
+
172
+
167
173
  ```

1

サンプルソースを追記

2020/06/24 09:13

投稿

yymmt
yymmt

スコア1615

test CHANGED
@@ -17,3 +17,151 @@
17
17
 
18
18
 
19
19
  複数のプロセス間でこれを行う場合、排他処理として空のファイルを作ることをやります。停止させたい場合にあるディレクトリに空ファイルを置くとプログラムが停止する、というような方式です。
20
+
21
+
22
+
23
+ #### サンプルソース
24
+
25
+ 1秒毎に時刻を表示します。GUIでSTART/STOPが可能です。GUIの作成とスレッド作成を同じJobManagerクラス内に閉じ込めることで、メンバ変数を使ってstart/stopを制御しています。
26
+
27
+
28
+
29
+ ```python
30
+
31
+ import datetime
32
+
33
+ import schedule
34
+
35
+ import sys
36
+
37
+ import threading
38
+
39
+ import tkinter as tk
40
+
41
+
42
+
43
+ MONITOR_PERIOD = 1
44
+
45
+
46
+
47
+
48
+
49
+ def now():
50
+
51
+ return datetime.datetime.now().strftime("%Y年%m月%d日 %H:%M:%S")
52
+
53
+
54
+
55
+
56
+
57
+ class JobManager:
58
+
59
+ def __init__(self, root):
60
+
61
+ self.root = root
62
+
63
+ self.running = True
64
+
65
+ self.job_enable = True
66
+
67
+ self.time = tk.StringVar()
68
+
69
+
70
+
71
+ # GUIの準備
72
+
73
+ frame = tk.Frame(root)
74
+
75
+ frame.pack()
76
+
77
+ button_start = tk.Button(frame, text="Start", command=self.start)
78
+
79
+ button_start.pack(side=tk.LEFT)
80
+
81
+ button_stop = tk.Button(frame, text="Stop", command=self.stop)
82
+
83
+ button_stop.pack(side=tk.LEFT)
84
+
85
+ button = tk.Button(frame, text="Quit", fg="red", command=self.quit)
86
+
87
+ button.pack(side=tk.LEFT)
88
+
89
+ label_time = tk.Label(root, textvariable=self.time)
90
+
91
+ label_time.pack()
92
+
93
+
94
+
95
+ # ジョブのスケジューリング
96
+
97
+ schedule.every(MONITOR_PERIOD).seconds.do(self.job)
98
+
99
+
100
+
101
+ # スレッドの開始
102
+
103
+ self.thread = threading.Thread(target=self.run_monitor)
104
+
105
+ self.thread.start()
106
+
107
+
108
+
109
+ def run_monitor(self):
110
+
111
+ schedule.run_pending()
112
+
113
+ if not self.running:
114
+
115
+ sys.exit(1)
116
+
117
+ self.root.after(200, self.run_monitor)
118
+
119
+
120
+
121
+ def job(self):
122
+
123
+ if self.job_enable:
124
+
125
+ self.time.set(now())
126
+
127
+
128
+
129
+ def start(self):
130
+
131
+ self.job_enable = True
132
+
133
+
134
+
135
+ def stop(self):
136
+
137
+ self.job_enable = False
138
+
139
+ self.time.set("Job is disabled")
140
+
141
+
142
+
143
+ def quit(self):
144
+
145
+ self.running = False
146
+
147
+
148
+
149
+
150
+
151
+ def main():
152
+
153
+ root = tk.Tk()
154
+
155
+ JobManager(root)
156
+
157
+ root.mainloop()
158
+
159
+
160
+
161
+
162
+
163
+ if __name__ == "__main__":
164
+
165
+ main()
166
+
167
+ ```