現在tkinterとPygameを用いてゲームコントローラーの入力回数をカウントし、押した部分が変色するようなGUiアプリを開発しようとしています。カウントを表示する部分はうまくいったのですが、押した箇所の色を変えることができません。
外観
1枚のディスクと7つのボタンを操作するゲーム(beatmania IIDXで検索していただけるとわかると思います)のコントローラーを使用しています。ボタンを押すorディスクを回すと該当部分のカウンターが更新されます。
ソースコード
python
1import os 2import sys 3import time 4import threading 5os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide' 6import pygame 7from pygame.locals import * 8import tkinter 9from tkinter import font, IntVar 10 11class GUI(threading.Thread): 12 def __init__(self, title, key_input): 13 self.title = title 14 self.key_input = key_input 15 self.is_running = False 16 threading.Thread.__init__(self) 17 self.setDaemon(True) 18 self.start() 19 20 def count_up(self, idx): 21 if self.is_running: 22 self.label_value[idx].set(self.label_value[idx].get()+1) 23 24 def quit(self): 25 if self.is_running: 26 self.is_running = False 27 self.window.quit() 28 29 def lightning(self, idx, flag): 30 if self.is_running: 31 self.is_lightning[idx] = flag 32 33 def run(self): 34 self.window = tkinter.Tk() 35 self.window.title(self.title) 36 self.window.geometry('640x360') 37 canvas = tkinter.Canvas(self.window, width = 640, height = 360) 38 # 白鍵盤 39 for i in range(4): 40 canvas.create_rectangle(280+90*i, 195, 350+90*i, 330) 41 # 黒鍵盤 42 for i in range(3): 43 canvas.create_rectangle(325+90*i, 30, 395+90*i, 165, fill = 'black') 44 # 皿 45 canvas.create_oval(35, 65, 255, 285) 46 47 canvas.place(x=0, y=0) 48 49 l = len(self.key_input) 50 self.label = [None]*l 51 self.label_value = [IntVar(value=v) for v in self.key_input] 52 self.is_lightning = [False for _ in self.key_input] 53 font1 = font.Font(family='Bauhaus93', size=10, weight='bold') 54 55 56 #常時更新部分 57 for i in range(8): 58 if(self.is_lightning[i]): 59 if(i < 7): 60 if(i % 2 == 0): 61 j = i % 2 62 canvas.create_rectangle(282+90*j, 197, 348+90*j, 328, fill = 'red') 63 else: 64 j = i % 2 65 canvas.create_rectangle(327+90*i, 32, 393+90*i, 163, fill = 'red') 66 else: 67 canvas.create_oval(37, 67, 253, 283, fill = 'red') 68 69 70 for i in range(l): 71 self.label[i] = tkinter.Label( 72 self.window, font=font1, textvariable=self.label_value[i] 73 ) 74 self.label[i].place(x=310+45*i, y=(5 if i < 7 and i%2 else 333)) 75 self.label[7].place(x=205, y=300) 76 77 self.is_running = True 78 self.window.mainloop() 79 80 81if __name__ == '__main__': 82 pygame.init() 83 lightning_time = [time.time() for _ in range(8)] 84 try: 85 joystick = pygame.joystick.Joystick(0) 86 joystick.init() 87 except pygame.error: 88 print('ジョイスティックが接続されていません', file=sys.stderr) 89 sys.exit(1) 90 91 # Show joystick's specification 92 print(f'ジョイスティックの名前: {joystick.get_name()}') 93 print(f'ボタン数: {joystick.get_numbuttons()}') 94 95 # Create Tkinter Window within another thread 96 size = 8 97 key_input = [0]*size 98 g = GUI('Contoller input', key_input) 99 100 # Event loop 101 past_time = time.time() 102 flag_roop = True 103 while flag_roop: 104 now_time = time.time() 105 for e in pygame.event.get(): 106 if(e.type == QUIT): 107 flag_roop = False 108 pygame.quit() 109 g.quit() 110 window.quit() 111 exit() 112 sys.exit() 113 if(e.type == pygame.locals.JOYBUTTONDOWN): 114 print(f'press button: {e.button}') 115 if 0 <= e.button < size-1: 116 lightning_time[e.button] = now_time 117 g.count_up(e.button) 118 if(e.type == pygame.locals.JOYAXISMOTION): #LR2 Type 119 delta_time = now_time - past_time 120 lightning_time[7] = now_time 121 if(e.value < 0): 122 if(0.19 > delta_time or delta_time > 0.22): 123 print('Turntable spin to right') 124 g.count_up(size-1) 125 if(e.value > 0): 126 g.count_up(size-1) 127 print('Turntable spin to left') 128 past_time = now_time 129 for i in range(8): 130 delta_time2 = now_time - lightning_time[i] 131 if(delta_time2 < 0.3): 132 g.lightning(i, True) 133 else: 134 g.lightning(i, False) 135
ligntning関数を用いてボタンを光らせているかの判定をしたく、ボタンを押してから0.3秒間はGUIの該当部分を赤くするようにしたいのですが、現状では図形が上の画像のまま変色しません。どこを改善したらよいかご教授お願い致します。
追記
shiracamusさんの記述を参考にしたのですが、main関数にて記述したpygameの部分が認識されません。ターミナルにもprintで来ていない状態です。
python
1import os 2import sys 3import time 4import threading 5import pygame 6from pygame.locals import * 7os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide' 8import tkinter as tk 9from tkinter import font, IntVar 10 11 12class Switch: 13 14 def __init__(self, canvas, shape, x1, y1, x2, y2, color): 15 self.canvas = canvas 16 self.on = shape(x1, y1, x2, y2, fill='red') 17 self.off = shape(x1, y1, x2, y2, fill=color) 18 self.count = IntVar() 19 20 def push(self): 21 self.count.set(self.count.get() + 1) 22 self.light_on() 23 24 def light_on(self): 25 self.canvas.tag_raise(self.on, self.off) 26 self.canvas.after(300, self.light_off) 27 28 def light_off(self): 29 self.canvas.tag_raise(self.off, self.on) 30 31 32class Key(Switch): 33 34 def __init__(self, canvas, x, y, width=70, height=135, color='white'): 35 super().__init__(canvas, canvas.create_rectangle, 36 x, y, x + width, y + height, color) 37 38 39class Disk(Switch): 40 41 def __init__(self, canvas, x, y, size, color='white'): 42 super().__init__(canvas, canvas.create_oval, 43 x, y, x + size, y + size, color) 44 45 46class Game: 47 48 def __init__(self, title): 49 self.title = title 50 51 def run(self): 52 self.running = True 53 self.window = tk.Tk() 54 self.window.title(self.title) 55 self.window.geometry('640x360') 56 57 self.switches = self._make_switches() 58 59 self.window.after(1000, self._check_to_quit) 60 self.window.mainloop() 61 # need to delete variables that reference tkinter objects in the thread 62 del self.switches 63 del self.window 64 65 def _make_switches(self): 66 canvas = tk.Canvas(self.window, width=640, height=360) 67 canvas.place(x=0, y=0) 68 69 white_keys = [Key(canvas, x, y=195) 70 for x in range(280, 280 + 90 * 4, 90)] 71 black_keys = [Key(canvas, x, y=30, color='black') 72 for x in range(325, 325 + 90 * 3, 90)] 73 disk = Disk(canvas, x=35, y=65, size=220) 74 75 font1 = font.Font(family='Bauhaus93', size=10, weight='bold') 76 for i, key in enumerate(white_keys): 77 label = tk.Label(self.window, font=font1, textvariable=key.count) 78 label.place(x=310 + 90 * i, y=333) 79 for i, key in enumerate(black_keys): 80 label = tk.Label(self.window, font=font1, textvariable=key.count) 81 label.place(x=355 + 90 * i, y=5) 82 label = tk.Label(self.window, font=font1, textvariable=disk.count) 83 label.place(x=205, y=300) 84 85 return dict(zip((0, 2, 4, 6, 1, 3, 5, 7), 86 (*white_keys, *black_keys, disk))) 87 88 def push_switch(self, index): 89 self.switches[index].push() 90 91 def _check_to_quit(self): 92 if self.running: 93 self.window.after(1000, self._check_to_quit) 94 else: 95 self.window.destroy() 96 97 def quit(self): 98 self.running = False 99 100def main(): 101 game = Game('Contoller input') 102 thread = threading.Thread(target=game.run) 103 thread.start() 104 pygame.joystick.init() 105 pygame.init() 106 107 try: 108 j = pygame.joystick.Joystick(0) # create a joystick instance 109 j.init() # init instance 110 print(j.get_name()) 111 except pygame.error: 112 print('Joystickが見つかりませんでした。') 113 game.quit() 114 115 for e in pygame.event.get(): 116 print(e) 117 if(e.type == pygame.locals.JOYBUTTONDOWN or e.type == pygame.locals.JOYAXISMOTION or e.type == QUIT): 118 if(e.type == QUIT): 119 print("quit") 120 game.quit() 121 thread.join() 122 if(e.type == pygame.locals.JOYBUTTONDOWN): 123 print("button " + str(e.button)) 124 if(e.button < 7): 125 game.push_switch(e.button) 126 elif(e.type == pygame.locals.JOYAXISMOTION): 127 print("turntable spin") 128 game.push_switch(7) 129 130if __name__ == '__main__': 131 main()
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/02/11 07:49
2020/02/11 08:04
2020/02/11 08:26
2020/02/11 16:15
2020/02/13 06:28
2020/02/13 06:35 編集
2020/02/15 09:08
2020/02/16 01:41 編集
2020/02/16 01:47 編集
2020/02/16 07:42
2020/02/16 09:54