-
Notifications
You must be signed in to change notification settings - Fork 3
/
wxAutoMine.py
441 lines (410 loc) · 19.5 KB
/
wxAutoMine.py
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
#!/usr/local/bin/python
# -*- coding: utf-8 -*-
'''wxAutoMine
Copyright(C) 2012 idobatter, All Rights Reserved.
SoftwareDesign 2012-03 記事が動機 (Win7 / Python 2.5 / wxPython 2.8 で動作確認)
敢えて pywinauto SendKeys PIL 等は使用せず標準機能 (ctypes) と wx のみで動作
キー送信(F2:開始)とマウスクリック(左右中央)と画面キャプチャから各セル種の判定
※改善予定場所とバグ
OS (というか機種依存) の色設定によっては正常に動作しない場合がある
-> TrueColor 32bit なら正常動作 / HighColor 16bit だと誤動作
-> capture 画像の色が参照画像 (wxAutoMine.png) と一致しないため
-> CHKBMP の再出力で改善するが完全一致でないと誤動作 (白黒 2 値化してみる?)
真の推論モード(未開場所の共有数に基く仮定と矛盾の利用)は今のところ無し
-> 最初の数箇所は適当に開く
-> 数字と Box 数(未開) が一致しているとき右クリックで Box に旗を立てる
-> 別 Cell に移動して旗の数が数字と一致していたら残りの Box (未開) を全て開く
-> 繰り返し(ただしこのやり方だと推論が無いので終了しないケースが多い)
-> 数字と開封状態のパターン辞書を用意して擬似推論(公理定理系を構築)すると速い
-> 11- 12? 122 121 129 229 131 14- 等 (1221 など 2Cell に跨る物は未対応)
-> 終盤は左上に出てくる残り爆弾数も推論に利用可能(未対応)
-> それでも判別不能のケースがあるので無限ループにしない判定が必要
-> 知識不足/煮詰まったとき [じっくり考える 助言を待つ 適当に開く]
今のところレベルは上級者または上級者と同サイズで爆弾数増減のケースのみ対応
上級者サイズ以外の場合のサイズ判定をしたい
Alt-G-E を送信して上級者を強制選択しているが lparam が中途半端?で稀に誤動作
Windows XP だと HWND_TOPMOST が必須? Graphic Accelerator の問題?
target を HWND_TOPMOST にしている間は BalloonTip が一回しか表示されない
TARGETWCLASS が日本語版にしか対応していない (というか何故クラス名が日本語)
target (winmine.exe) を立ち上げる機能があると便利
思考モードで旗を立てるとき既に立っている場所を右クリックすると ? になるので注意
※最高記録
いまのところ上級者モードで 54 秒が最高 (SoftwareDesign の画像だと 37 秒)
wxAutoMine.py 2 つ同時起動だと 33 秒記録達成出来た !!!
-> 片方は動作速度をずらす / 最初に開く数を減らす / 序盤以外はリトライしない
もっと高速化する場合
-> multi thread にすると速くなりそう
-> INTERVAL を 50ms 以下にする (逆に reentry block に掛かって遅くなる場合あり)
-> あるいは EVT_PAINT は無視してクリックに徹する (wxPython 使わない)
-> updatepaint の描画中表示そのものを無くす (ほとんど変わらないかも)
-> memdc.py 中の BitBlt / gblit を最適化 (効率良くなれば高速化可能)
-> Grayscale (ConvertoToGreyscale) しない方が良いかもしれない (byte 3 倍注意)
-> capture 後全体を updatemap しているが gray 化を未開地だけに絞れば速くなる
-> 辞書を増やす (特に開ける場所が多く判明する pattern を増やす)
-> 「真の推論」と「辞書方式」のどちらが速いか検証必要
'''
from cwm import PostWinMsg
from memdc import MemDC
import AutoMineDict as AMD
import BalloonTipDict as BTD
import wx
import main_icon
APPTITLE = u'wxAutoMine'
TARGETWCLASS = u'マインスイーパ'
INTERVAL = 30 # msec
CLPW, CLPH = 8, 4
ADJW, ADJH = 7, 8
OFFSETW, OFFSETH = 20, 64
CELLW, CELLH = 16, 16
LEVELHW, LEVELHH = 30, 16 # 今のところ上級者サイズ固定(爆弾数は増減可能)
PANELHW, PANELHH = (OFFSETW + CELLW * LEVELHW), (OFFSETH + CELLH * LEVELHH)
GENERATE_CHKBMP = None
# GENERATE_CHKBMP = u'chkbmp.txt' # to generate CHKBMP strings
CHKBMP = [
'ffffffffffffffffffc0c0c0c0c0c0c0ffc0c0c0c0c0c0c0ffc0c0c0c0c0c0c0', # f box
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0', # 0 none
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c01dc0c0c0c0c0c01d1d', # 1
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c04b4b4b4b4bc0c04b4b4b4b4b4b', # 2
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c04c4c4c4c4c4cc0c04c4c4c4c4c4c', # 3
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00f0f0fc0c0c0c0c00f0f0fc0', # 4
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0262626262626c0c0262626262626', # 5
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c05a5a5a5a5ac0c05a5a5a5a5a5a', # 6
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0000000000000c0c0000000000000', # 7
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c08080808080c0c0808080808080', # 8
'ffffffffffffffffffc0c0c0c0c0c0c0ffc0c0c0c0c04c4cffc0c0c04c4c4c4c', # 9 flag
'c0c0c0c0c0c0c0c0c0c0c0c0c0c0c000c0c0c0c0c0c0c000c0c0c000c0000000', # a bomb
'4c4c4c4c4c4c4c4c4c4c4c4c4c4c4c004c4c4c4c4c4c4c004c4c4c004c000000', # b crash
'ffffffffffffffffffc0c0c0c0c0c0c0ffc0c0c0c0000000ffc0c0c00000c0c0', # c '?'
'e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e20000000000000000000000e200000000', # d good
'e2e2e2e2e2e2e2e2e200e2e2e200e20000e2e2e2e2e200e2e200e2e2e200e200'] # e miss
class MyFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(MyFrame, self).__init__(title=APPTITLE,
size=(800, 600), pos=(520, 240), *args, **kwargs)
self.SetIcon(main_icon.getIcon()) # img2py -i main_icon.ico main_icon.py
hsz = wx.BoxSizer(wx.HORIZONTAL)
vpnl = wx.Panel(self, -1)
vpnl.SetBackgroundColour(wx.Colour(240, 192, 32))
vsz00 = wx.BoxSizer(wx.VERTICAL)
self.clock = wx.StaticText(vpnl, -1, u'動作速度 clock %dms' % INTERVAL)
vsz00.Add(self.clock, 0, wx.EXPAND)
self.clockslider = wx.Slider(vpnl, wx.NewId(), INTERVAL, 1, 500)
vsz00.Add(self.clockslider, 0, wx.EXPAND)
self.timesfirst = wx.StaticText(vpnl, -1, u'最初に開く場所 7ヶ所')
vsz00.Add(self.timesfirst, 0, wx.EXPAND)
self.timesfirstslider = wx.Slider(vpnl, wx.NewId(), 7, 1, 20)
vsz00.Add(self.timesfirstslider, 0, wx.EXPAND)
self.timestrunc = wx.StaticText(vpnl, -1, u'下の行動に遷移するまで 2')
vsz00.Add(self.timestrunc, 0, wx.EXPAND)
self.timestruncslider = wx.Slider(vpnl, wx.NewId(), 2, 2, 200)
vsz00.Add(self.timestruncslider, 0, wx.EXPAND)
self.choices = [u'じっくり考える', u'助言を待つ', u'適当に開く']
self.suggestion = wx.RadioBox(vpnl, wx.NewId(), u'知識不足/煮詰まったとき',
choices=self.choices, majorDimension=3, style=wx.RA_SPECIFY_COLS)
self.suggestion.EnableItem(0, False)
self.suggestion.SetSelection(2)
vsz00.Add(self.suggestion, 0, wx.EXPAND)
hsz0 = wx.BoxSizer(wx.HORIZONTAL)
self.stmisscont = wx.StaticText(vpnl, -1, u'失敗時の自動リトライ')
hsz0.Add(self.stmisscont, 1, wx.EXPAND)
self.misscont1 = wx.CheckBox(vpnl, wx.NewId(), u'序盤')
self.misscont1.SetValue(True)
hsz0.Add(self.misscont1, 0, wx.EXPAND)
self.misscont2 = wx.CheckBox(vpnl, wx.NewId(), u'序盤以外')
self.misscont2.SetValue(True)
hsz0.Add(self.misscont2, 0, wx.EXPAND)
vsz00.Add(hsz0, 0, wx.EXPAND)
self.btnpause = wx.Button(vpnl, wx.NewId(), u'Pause')
vsz00.Add(self.btnpause, 0, wx.EXPAND)
hsz00 = wx.BoxSizer(wx.HORIZONTAL)
self.showinfer = wx.CheckBox(vpnl, wx.NewId(), u'推論状態表示')
self.showinfer.SetValue(False)
hsz00.Add(self.showinfer, 1, wx.EXPAND)
self.showdict = wx.CheckBox(vpnl, wx.NewId(), u'辞書検出表示')
self.showdict.SetValue(True)
hsz00.Add(self.showdict, 1, wx.EXPAND)
self.showmap = wx.CheckBox(vpnl, wx.NewId(), u'内部状態表示')
self.showmap.SetValue(False)
hsz00.Add(self.showmap, 1, wx.EXPAND)
vsz00.Add(hsz00, 0, wx.EXPAND)
self.txt = wx.TextCtrl(vpnl, style=wx.TE_MULTILINE)
vsz00.Add(self.txt, 3, wx.EXPAND)
self.ptn = wx.TextCtrl(vpnl, style=wx.TE_MULTILINE)
vsz00.Add(self.ptn, 3, wx.EXPAND)
self.msg = wx.TextCtrl(vpnl, style=wx.TE_MULTILINE)
vsz00.Add(self.msg, 2, wx.EXPAND)
vpnl.SetSizer(vsz00)
hsz.Add(vpnl, 1 if GENERATE_CHKBMP else 4, wx.EXPAND)
vsz01 = wx.BoxSizer(wx.VERTICAL)
self.map = wx.TextCtrl(self, style=wx.TE_MULTILINE)
self.map.SetFont(wx.Font(8, wx.TELETYPE, wx.NORMAL, wx.NORMAL)) # wx.MODERN
vsz01.Add(self.map, 4, wx.EXPAND)
self.cap = wx.Panel(self, size=(PANELHW, PANELHH))
vsz01.Add(self.cap, 5, wx.EXPAND)
hsz.Add(vsz01, 3 if GENERATE_CHKBMP else 7, wx.EXPAND)
self.SetSizer(hsz)
self.btd = BTD.BalloonTipDict(main_icon.getBitmap())
self.blnclock = self.btd.get(self, 'clock')
self.blntimestrunc = self.btd.get(self, 'timestrunc')
self.blnstmisscont = self.btd.get(self, 'stmisscont')
wx.CallAfter(self.setup)
def setup(self):
self.amd = AMD.AutoMineDict()
self.x, self.y = 0, 0
self.gcount, self.count, self.phase, self.roll = 0, 0, 0, []
self.fixed = [False] * (LEVELHW * LEVELHH)
self.ldelta = [(-1, -1), (0, -1), (1, -1),
(-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)]
self.mdc = MemDC(wx.ClientDC(self.cap), wx.Colour(0, 0, 0))
self.chkbmp = {}
self.loadrefimg()
self.maptbl = [0xff] * (LEVELHW * LEVELHH)
self.target, self.pwm = None, None
self.tick1 = False
self.timer1 = wx.Timer(self, wx.NewId())
self.Bind(wx.EVT_TIMER, self.onTick, self.timer1)
self.Bind(wx.EVT_SLIDER, self.onClockSlider, self.clockslider)
self.Bind(wx.EVT_SLIDER, self.onTimesFirstSlider, self.timesfirstslider)
self.Bind(wx.EVT_SLIDER, self.onTimesTruncSlider, self.timestruncslider)
self.Bind(wx.EVT_RADIOBOX, self.onSuggestion, self.suggestion)
self.Bind(wx.EVT_CHECKBOX, self.onMisscont, self.misscont1)
self.Bind(wx.EVT_CHECKBOX, self.onMisscont, self.misscont2)
self.Bind(wx.EVT_CHECKBOX, self.onShowinfer, self.showinfer)
self.Bind(wx.EVT_CHECKBOX, self.onShowdict, self.showdict)
self.Bind(wx.EVT_CHECKBOX, self.onShowmap, self.showmap)
self.Bind(wx.EVT_BUTTON, self.onPause, self.btnpause)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.onPause(None)
def loadrefimg(self):
if GENERATE_CHKBMP:
bm = wx.Bitmap(u'%s.png' % APPTITLE)
self.mdc.gblit(PANELHW, OFFSETH, None, None, bm, 0, 0)
fp = open(GENERATE_CHKBMP, 'wb')
for i in xrange(14):
buf = self.mdc.gclip(CLPW, CLPH, PANELHW + 1, OFFSETH + CELLH * i + 1)
fp.write('%s\n' % buf.encode('hex'))
for i in xrange(2):
buf = self.mdc.gclip(CLPW, CLPH,
PANELHW + 32 + 18 * i, OFFSETH + CELLH * 15 - 4)
fp.write('%s\n' % buf.encode('hex'))
fp.close()
for i, h in enumerate(CHKBMP):
self.chkbmp[h.decode('hex')] = i - 1 if i > 0 else 0xff
def maptxt(self, buf, w, dlm=None, fmt=None):
s = []
for y in xrange(len(buf) / w):
for x in xrange(w):
if x and dlm: s.append(dlm)
s.append((fmt if fmt else '%02x') % buf[y * w + x])
s.append('\n')
return ''.join(s)
def updatemap(self):
for y in xrange(LEVELHH):
for x in xrange(LEVELHW):
k = self.mdc.gclip(CLPW, CLPH,
OFFSETW - ADJW + CELLW * x, OFFSETH - ADJH + CELLH * y)
self.maptbl[y * LEVELHW + x] = self.chkbmp[k] & 0x0f if \
self.chkbmp.has_key(k) else 0xee
def updatepaint(self, dc):
self.map.Clear()
if self.showmap.GetValue():
self.mdc.flush()
self.map.WriteText(self.maptxt(self.maptbl, LEVELHW, ' ', '%x'))
else:
bdc = wx.BufferedDC(dc)
bdc.Clear()
bdc.DrawText(u'描画休止中(少しだけ高速化)', 80, 40)
def isover(self):
k = self.mdc.gclip(CLPW, CLPH, OFFSETW + CELLW * 14 + 5, 23)
if not self.chkbmp.has_key(k): return 0
return self.chkbmp[k] - 12 if self.chkbmp[k] else 0
def num(self, x, y):
if x < 0 or y < 0: return None
if x >= LEVELHW or y >= LEVELHH: return None
return self.maptbl[y * LEVELHW + x]
def countaround(self, x, y):
'''return count of flagged cell, opened cell, closed cell, r, l(=ptn)'''
f, o, c, r, l = 0, 0, 0, set(), []
for dx, dy in self.ldelta:
n = self.num(x + dx, y + dy)
if n is None:
l.append(0)
continue
l.append(n)
if n == 9: f += 1
if 0 <= n <= 8: o += 1
if n == 0x0f or n == 0x0c or n == 9:
c += 1
if n != 9: r.add((x + dx, y + dy)) # 二重 click 防止
l[4:4] = [self.num(x, y)]
return f, o, c, r, ''.join(hex(b)[-1] for b in l)
def loginfer(self, s):
if self.showinfer.GetValue(): self.txt.AppendText(s)
def guess(self):
import random
self.loginfer(u'guess...')
for _ in xrange(100): # block endress loop 効率悪 直接未開地を探す方が速い
self.x = random.randint(0, LEVELHW - 1)
self.y = random.randint(0, LEVELHH - 1)
if self.num(self.x, self.y) == 0x0f: break
self.loginfer(u'[%d, %d]' % (self.x, self.y))
return [], set(((self.x, self.y),)), set() # always to be opened
def infer(self):
self.count += 1 # 手数
if self.count <= self.timesfirstslider.GetValue(): return self.guess()
if self.count - self.gcount <= 1: return self.guess() # 1 回だけ適当に開く
self.loginfer(u'infer(%d, %d)...' % (self.x, self.y))
roll = []
while True: # 必ず最後は roll で break するので無限ループにはならない
x, y = self.x, self.y
self.x += 1
if self.x >= LEVELHW: self.x, self.y = 0, self.y + 1
if self.y >= LEVELHH: self.y = 0
if not self.fixed[y * LEVELHW + x]:
n = self.num(x, y)
if 1 <= n <= 8:
self.loginfer(u'%d[%d, %d]' % (n, x, y))
roll.append((x, y))
f, o, c, r, l = self.countaround(x, y)
k, m = self.amd.match(l)
lop, lmk = set(), set()
if k:
if self.showdict.GetValue():
self.ptn.AppendText(u'%d[%d, %d]p[%s]q[%s]\n' % (n, x, y, l, k))
self.ptn.AppendText(u'k[%s]m%dr%d\n' % (m[0], m[1], m[2]))
self.ptn.AppendText(u'o%s\nm%s\n' % (repr(m[3]), repr(m[4])))
for p in m[3]: # lop
px, py = x + p[0], y + p[1]
b = self.num(px, py)
if b == 0x0f or b == 0x0c: lop.add((px, py)) # 二重 click 防止
for p in m[4]: # lmk
px, py = x + p[0], y + p[1]
b = self.num(px, py)
if b != 9: lmk.add((px, py)) # 二重 click 防止
if len(r) == 0: self.fixed[y * LEVELHW + x] = True
if f == n: return roll, lop.union(r), lmk # to be opened
if c == n: return roll, lop, lmk.union(r) # to be marked
# 戻った先でも lop lmk check しているが ここは roll 検出のため必要
if k and (len(lop) or len(lmk)): return roll, lop, lmk
if self.x == 0 and self.y == 0: break
return roll, set(), set()
def click(self, b, x, y):
if x < 0 or y < 0: return 0
if x >= LEVELHW or y >= LEVELHH: return 0
self.loginfer(u'%c(%d, %d)' % ('m' if b else 'o', x, y))
self.pwm.mouseclk(b, OFFSETW + CELLW * x, OFFSETH + CELLH * y) # btn L / R
return 1
def onTick(self, ev):
if self.timer1.GetId() != ev.GetId(): return
if self.tick1: return
self.tick1 = True
while True: # 除外処理系を break & 最後に break で脱出 (indent 減らすため)
if self.target is None:
self.msg.AppendText(u'Searching %s ...' % TARGETWCLASS)
self.target = PostWinMsg.target(TARGETWCLASS, TARGETWCLASS)
if self.target == 0:
self.msg.AppendText(u'may not be running.\n')
self.target = None
break
self.msg.AppendText(u'is found.\n')
self.pwm = PostWinMsg(self.target, wait=0, fg=False)
# self.msg.AppendText(self.pwm.getclassname(len(TARGETWCLASS)))
self.pwm.topmost()
self.pwm.altkeys('GE') # Alt-G-E select high level
self.pwm.keydu(113) # VK_F2 restart
self.pwm.sleep(INTERVAL * 4)
self.txt.Clear()
self.ptn.Clear()
self.amd.reload()
self.x, self.y = 0, 0
self.gcount, self.count, self.phase, self.roll = 0, 0, 0, []
self.fixed = [False] * (LEVELHW * LEVELHH)
break
self.mdc.gcapture(0, 0, PANELHW, PANELHH, self.target, 0, 0)
self.updatemap()
self.updatepaint(wx.ClientDC(self.cap))
o = self.isover()
if o == 1:
self.msg.AppendText(u'completed\n')
self.onPause(None)
self.target = None
# self.pwm.wm(18, 0, 0) # WM_QUIT
break
elif o == 2:
self.msg.AppendText(u'missed never give up\n')
if self.count <= self.timesfirstslider.GetValue() \
and self.misscont1.GetValue(): # 序盤(規定手数内)の失敗続行
self.pwm.topmost(False)
elif self.count > self.timesfirstslider.GetValue() \
and self.misscont2.GetValue(): # 序盤以外の失敗続行
self.pwm.topmost(False)
else: self.onPause(None)
self.target = None
break
roll, lop, lmk = self.infer()
if len(lop) or len(lmk):
c = 0
for x, y in lop: c += self.click(0, x, y) # open many boxes
for x, y in lmk: c += self.click(1, x, y) # block '?' from double click
if c: self.pwm.sleep(INTERVAL) # redraw (block reentry self.tick1)
else:
self.loginfer(u'roll\n')
if roll == self.roll: self.phase += 1
if self.phase >= self.timestruncslider.GetValue(): # 行動遷移
if self.suggestion.GetSelection() == 1:
self.msg.AppendText(u'I want your suggestion, and resume it.\n')
self.onPause(None)
else: self.gcount = self.count
self.phase = 0
self.roll = roll
break
self.tick1 = False
def onClockSlider(self, ev):
self.clock.SetLabel(u'動作速度 clock %dms' % (self.clockslider.GetValue()))
def onTimesFirstSlider(self, ev):
self.timesfirst.SetLabel(u'最初に開く場所 %dヶ所' % (
self.timesfirstslider.GetValue()))
def onTimesTruncSlider(self, ev):
self.timestrunc.SetLabel(u'下の行動に遷移するまで %d' % (
self.timestruncslider.GetValue()))
def onSuggestion(self, ev):
self.msg.AppendText(u'suggestion=%d\n' % self.suggestion.GetSelection())
def onMisscont(self, ev):
self.msg.AppendText(u'misscont%d=%d\n' % (
1 if ev.GetId() == self.misscont1.GetId() else 2,
ev.GetEventObject().GetValue()))
def onShowinfer(self, ev):
self.msg.AppendText(u'showinfer=%d\n' % self.showinfer.GetValue())
def onShowdict(self, ev):
self.msg.AppendText(u'showdict=%d\n' % self.showdict.GetValue())
def onShowmap(self, ev):
self.msg.AppendText(u'showmap=%d\n' % self.showmap.GetValue())
def onPause(self, ev):
if self.timer1.IsRunning():
self.msg.AppendText(u'pause...\n')
self.btnpause.SetLabel(u'Resume')
self.timer1.Stop()
if self.pwm: self.pwm.topmost(False) # after stop timer
else:
self.msg.AppendText(u'running...\n')
self.btnpause.SetLabel(u'Pause')
if self.pwm: self.pwm.topmost(True) # before start timer
self.timer1.Start(
milliseconds=self.clockslider.GetValue(), oneShot=False)
def OnPaint(self, ev):
dc = wx.PaintDC(self) # Don't delete this line
wx.CallAfter(self.updatepaint, wx.ClientDC(self.cap))
def OnClose(self, ev):
if self.timer1.IsRunning(): self.timer1.Stop()
if self.pwm: self.pwm.topmost(False)
self.Destroy()
class MyApp(wx.App):
def OnInit(self):
self.frm = MyFrame(None, wx.NewId())
self.SetTopWindow(self.frm)
self.frm.Show()
return True
if __name__ == '__main__':
app = MyApp()
app.MainLoop()