質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Pygame

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

1回答

1623閲覧

tkinterで動的に図形を更新したい

k0gane

総合スコア10

Pygame

Pygameは、ビデオゲームの製作用に設計されたクロスプラットフォームのPythonモジュールセットです。Pythonでコンピューターグラフィックスと音声を扱うためのライブラリが含まれています。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/02/11 05:01

編集2020/02/15 09:10

現在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()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

色を戻すのは、tk部品の afterを使えばいいですよ。

tkinterだけの処理を書いてみました。
このプログラムだけで動作確認してみてください。

python

1import os 2import sys 3import time 4import threading 5os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide' 6import tkinter as tk 7from tkinter import font, IntVar 8 9 10class Switch: 11 12 def __init__(self, canvas, shape, x1, y1, x2, y2, color): 13 self.canvas = canvas 14 self.on = shape(x1, y1, x2, y2, fill='red') 15 self.off = shape(x1, y1, x2, y2, fill=color) 16 self.count = IntVar() 17 18 def push(self): 19 self.count.set(self.count.get() + 1) 20 self.light_on() 21 22 def light_on(self): 23 self.canvas.tag_raise(self.on, self.off) 24 self.canvas.after(300, self.light_off) 25 26 def light_off(self): 27 self.canvas.tag_raise(self.off, self.on) 28 29 30class Key(Switch): 31 32 def __init__(self, canvas, x, y, width=70, height=135, color='white'): 33 super().__init__(canvas, canvas.create_rectangle, 34 x, y, x + width, y + height, color) 35 36 37class Disk(Switch): 38 39 def __init__(self, canvas, x, y, size, color='white'): 40 super().__init__(canvas, canvas.create_oval, 41 x, y, x + size, y + size, color) 42 43 44class Game: 45 46 def __init__(self, title): 47 self.title = title 48 49 def run(self): 50 self.running = True 51 self.window = tk.Tk() 52 self.window.title(self.title) 53 self.window.geometry('640x360') 54 55 self.switches = self._make_switches() 56 57 self.window.after(1000, self._check_to_quit) 58 self.window.mainloop() 59 # need to delete variables that reference tkinter objects in the thread 60 del self.switches 61 del self.window 62 63 def _make_switches(self): 64 canvas = tk.Canvas(self.window, width=640, height=360) 65 canvas.place(x=0, y=0) 66 67 white_keys = [Key(canvas, x, y=195) 68 for x in range(280, 280 + 90 * 4, 90)] 69 black_keys = [Key(canvas, x, y=30, color='black') 70 for x in range(325, 325 + 90 * 3, 90)] 71 disk = Disk(canvas, x=35, y=65, size=220) 72 73 font1 = font.Font(family='Bauhaus93', size=10, weight='bold') 74 for i, key in enumerate(white_keys): 75 label = tk.Label(self.window, font=font1, textvariable=key.count) 76 label.place(x=310 + 90 * i, y=333) 77 for i, key in enumerate(black_keys): 78 label = tk.Label(self.window, font=font1, textvariable=key.count) 79 label.place(x=355 + 90 * i, y=5) 80 label = tk.Label(self.window, font=font1, textvariable=disk.count) 81 label.place(x=205, y=300) 82 83 return dict(zip((0, 2, 4, 6, 1, 3, 5, 7), 84 (*white_keys, *black_keys, disk))) 85 86 def push_switch(self, index): 87 self.switches[index].push() 88 89 def _check_to_quit(self): 90 if self.running: 91 self.window.after(1000, self._check_to_quit) 92 else: 93 self.window.destroy() 94 95 def quit(self): 96 self.running = False 97 98def main(): 99 game = Game('Contoller input') 100 thread = threading.Thread(target=game.run) 101 thread.start() 102 103 time.sleep(1) 104 for i in range(8): 105 game.push_switch(i) 106 time.sleep(1) 107 108 game.quit() 109 thread.join() 110 111if __name__ == '__main__': 112 main()

pygameとの連携がうまく動かないということなら、以下のような単純化した処理に置き換えて動作核にしてみてはいかがですか?

py

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 Game: 13 14 def __init__(self, title): 15 self.title = title 16 17 def run(self): 18 self.running = True 19 while self.running: 20 time.sleep(1) 21 22 def push_switch(self, number): 23 print("push_switch:", repr(number)) 24 25 def quit(self): 26 self.running = False 27 28 29def main(): 30 game = Game('Contoller input') 31 thread = threading.Thread(target=game.run) 32 thread.start() 33 pygame.joystick.init() 34 pygame.init() 35 36 try: 37 j = pygame.joystick.Joystick(0) # create a joystick instance 38 j.init() # init instance 39 print(j.get_name()) 40 except pygame.error: 41 print('Joystickが見つかりませんでした。') 42 game.quit() 43 44 for e in pygame.event.get(): 45 print(e) 46 if(e.type == pygame.locals.JOYBUTTONDOWN or e.type == pygame.locals.JOYAXISMOTION or e.type == QUIT): 47 if(e.type == QUIT): 48 print("quit") 49 game.quit() 50 thread.join() 51 if(e.type == pygame.locals.JOYBUTTONDOWN): 52 print("button " + str(e.button)) 53 if(e.button < 7): 54 game.push_switch(e.button) 55 elif(e.type == pygame.locals.JOYAXISMOTION): 56 print("turntable spin") 57 game.push_switch(7) 58 59if __name__ == '__main__': 60 main()

投稿2020/02/11 07:28

編集2020/02/16 09:54
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k0gane

2020/02/11 07:49

どうやって組み込めばよいですかね...?
shiracamus

2020/02/11 08:04

根本的に作りを変えた方がいいですよ、オブジェクト指向を使って。 tkinter側だけ、ちょっと作ってみます。
k0gane

2020/02/11 08:26

よろしくお願いいたします。
shiracamus

2020/02/11 16:15

動作確認用コードを追記しておきました。
k0gane

2020/02/13 06:28

プログラムありがとうございます、確かにコントローラーの該当箇所が光ったと同時にカウンターが加算したのですが、これをコントローラー入力によって反映させるようにするにはどうしたらよいかってわかりますでしょうか。
shiracamus

2020/02/13 06:35 編集

main関数がpygame側の処理です。 コントローラが操作されたら、 game.push_switch(i) を呼び出せばいです。 その代わりにループして呼び出す処理を書いてあるだけです。
k0gane

2020/02/15 09:08

お世話になっております。返信を返すのが遅くなってしまい申し訳ありません。main関数にてpygameの処理を記述したのですが、コントローラーは認識するのですがボタンを押しても反応がありません。追記にて記述しました。
shiracamus

2020/02/16 01:41 編集

ジョイスティックのボタンを押したのですか? 私はジョイステックを持っていないので確認できません。 例えば、 for e in pygame.event.get(): の直前に time.sleep(1) game.push_switch(1) game.push_switch(2) game.push_switch(3) と書いて、光るか確認していただけますか? スレッドの起動完了待ちのため time.sleep(1) を入れてください。
shiracamus

2020/02/16 01:47 編集

以下のmain関数で、0~7の数字を入れて光ることは確認できました。 def main():  game = Game('Contoller input')  thread = threading.Thread(target=game.run)  thread.start()  time.sleep(1)   while True:   game.push_switch(int(input("key: ")))
k0gane

2020/02/16 07:42

光ることは確認できました。ジョイスティックとの連動がうまくいっていないみたいです。
shiracamus

2020/02/16 09:54

ジョイスティックについてはまったくわからないので、テスト用の処理を追記しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問