実現したいこと
- 1秒ごとに交互に処理を切り替えたい
前提
最近、VisualStudioCodeを用いPythonを勉強をしています。
ですが自分では実現不可能なことにぶつかり、
検索してもこのような事例は見つからず困り果てこのサイトを利用させていただきました。
それが「1秒ごとに交互に処理を切り替えたい」です。
例えば処理Aと処理Bが存在するとき、この処理を
A → 一秒待つ → B → 一秒待つ → A → 一秒待つ → B → 一秒待つ ……
というようなことをしたいのです。
ですが、自分の浅い知識で色々とやってみたのですがうまくいきません。
やってみたことは下記に記しておきます。
※処理A・Bをprintとしていますがこれは仮です。
※本来はフォームを表示したうえでフォーム上のキャンバスの上の画像の位置を切り替えたいです。
(ややこしかったらすみません)
※ただコードがどういう動きをしているか確かめている間は実際したかった処理A・Bをコメントアウトした後、
処理A・Bにprintを追記して動かしています
該当のソースコード※この中にやってみたことが書いてあります
Python
1#パターン1 2#予測:afterで処理を遅らせて1秒ずつ出力させる!完璧やなこいつは! 3def Roop: 4 if value % 2 == 0: 5 print('0') #処理A 6 value += 1 7 else: 8 print('1') #処理B 9 value += 1 10 root.after(1000, self.Roop) 11#結果:高速で0と1が出力される。 12 13#パターン2 14#予測:関数の外にafterを置けばいいのかな?これでたぶんおそらく大丈夫! 15def Roop: 16 if value % 2 == 0: 17 print('0') #処理A 18 value += 1 19 else: 20 print('1') #処理B 21 value += 1 22root.after(1000, Roop) 23#結果:高速で0と1が出力された後TypeError。メソッドRoopを見失ったとのこと 24 25#パターン3 26#予測:じゃあtimeで処理を止めてみよう!これでいけるやろ! 27def Roop 28 if value % 2 == 0: 29 print('0') #処理A 30 time.sleep(1) 31 value += 1 32 else: 33 print('1') #処理B 34 time.sleep(1) 35 value += 1 36 root.after(1000, self.Roop) 37#結果:0と1を1秒ごとに出力させることに成功。しかし用意していたフォームは出てこなくなる
最後に
私はプログラミング(C#)というものに昨年4月に初めて触れ、
Pythonに触れたのは今月の初め頃なのです。
知らないこと、わからないことがまだまだ多く、
知識も技術も実力不足としか形容のしようがありません。
皆皆様に比べればまだまだ若輩者ではありますが、
どうかお力添えをお願い申し上げます。
コメントを受けての補足
TakaiY さん
コメントありがとうございます。
確かにどこで呼び出しているかわかりづらかったですよね。
思慮が足りず申し訳ないです。
実際に呼び出しているのは下記のような形です。
Python
1class OtamesiRoop: 2 def __init__(self): 3 self.Roop() 4 5 def Roop(): 6 global value 7 if value % 2 == 0: 8 print('0') #処理A 9 value += 1 10 else: 11 print('1') #処理B 12 value += 1 13 root.after(1000, Roop)
のような形です。
使用したクラス自体はroot.mainloop()の1行上で
otamesi = OtamesiRoop()
とインスタンス化してます。
何分このような場所で質問することは初めてなので、
足りない点至らない点あるとは思いますが
何卒よろしくお願いいたします。
コメントを受けての使用したソースコード全体
Python
1import tkinter as tk 2import random 3import time 4 5value = 0 6 7#ウィンドウの横幅 8Window_Width = 600 9#ウィンドウの縦幅 10Window_Height = 600 11 12Cannon_Y = 550 13 14Enemy_Space_X = 100 15Enemy_Space_Y = 60 16Enemy_Move_Space_X = 20 17Enemy_Move_Speed = 2000 18Number_Of_Enemy = 18 19Enemy_Shoot_Interval = 200 20 21Collision_Detection = 300 22 23Bullet_Height = 10 24Bullet_Width = 2 25Bullet_Speed = 10 26 27Text_Good_Size = 10 28Text_Congratulations_Size = 50 29Text_GameClear_Size = 60 30Text_GameOver_Size = 90 31 32#砲台を設定するクラスの定義 33class Cannon: 34 #__init__=クラスのインスタンスの生成時自動呼出しされるメソッド 35 def __init__(self, x, y=Cannon_Y): #self=インスタンスを指し示す 36 # 37 self.x = x 38 self.y = y 39 #self.=Class Cannonの中のメソッドを使う 40 self.draw() 41 self.bind() 42 43 #画像の設置 44 def draw(self): 45 #tag=設置したイラストに名前を付ける 46 self.id = cv.create_image(self.x,self.y,image=cannon_Image,tag="cannon") 47 48 #画像にイベントを作成 49 def bind(self): 50 #ButtonPress-3=右クリック 51 cv.tag_bind(self.id, "<ButtonPress-3>", self.pressed) 52 #Button1-Motion=ウィジェット内でカーソルが動いたとき 53 cv.tag_bind(self.id, "<Motion>", self.dragged) 54 55 #キャンバス上で右クリックを押したときのイベントメソッド 56 def pressed(self, event): 57 #クラスMyBulletのインスタンスを作成 58 mybullet = MyBullet(event.x, self.y) 59 #クラスMyBulletのdrawメソッド 60 mybullet.draw() 61 #クラスMyBulletのshootメソッド 62 mybullet.shoot() 63 64 #キャンバス上でカーソルが動いた時のイベントメソッド 65 def dragged(self, event): 66 #event=イベントの 67 dx = event.x - self.x 68 #coords=指定した画像の座標の変更や情報の取得 69 self.x, self.y = cv.coords(self.id) 70 #coords(画像の指定, x座標, y座標) 71 cv.coords(self.id, self.x+dx, self.y) 72 self.x = event.x 73 74 def destroy(self): 75 #delete=指定した画像の消去 76 cv.delete(self.id) 77 78#発射する弾のクラス 79class MyBullet: 80 #最初に読み込まれるメソッドは__init__とするルールがある 81 def __init__(self, x, y): 82 self.x = x 83 self.y = y 84 85 #画像の設置 86 def draw(self): 87 #rectangle=長方形の設置(左上の座標,右下の座標,色の指定) 88 self.id = cv.create_rectangle(self.x-Bullet_Width, self.y+Bullet_Height, self.x+Bullet_Width, self.y-Bullet_Height, fill="blue") 89 90 def shoot(self): 91 if self.y >= 0: 92 #move=画像の移動(画像の指定,移動するx座標,移動するy座標) 93 cv.move(self.id, 0, -Bullet_Height) 94 self.y -= Bullet_Height 95 #同じクラスのメソッドdefeatを使用 96 self.defeat() 97 #after=処理を遅らせる(遅らせる秒数,経過後に実行するメソッド) 98 root.after(Bullet_Speed, self.shoot) 99 100 def defeat(self): 101 for enemy in enemies: 102 if ((self.x-enemy.x)**2+(self.y-enemy.y)**2) < Collision_Detection: 103 #existをFalseに 104 enemy.exist = False 105 #クラスenemyのメソッドdestroy 106 enemy.destroy() 107 #create_text=テキストの作成 108 cv.create_text(enemy.x, enemy.y, text="good!", fill="cyan", font=("System", Text_Good_Size), tag="good") 109 110 def destroy(self): 111 #画像の消去 112 cv.delete(self.id) 113 114 115#敵のクラス 116class Enemy: 117 #クラスのインスタンス生成時に起動 118 def __init__(self, x, y): 119 self.x = x % Window_Width 120 self.y = y+x//Window_Width*Enemy_Space_X 121 #existをtrueに 122 self.exist = True 123 #同じクラスのメソッドdraw 124 self.draw() 125 #同じクラスのメソッドmove 126 self.move() 127 128 def draw(self): 129 #画像の設置 130 self.id = cv.create_image(self.x, self.y, image=crab_Image, tag="enemy") 131 132 def enemy_shoot(self): 133 if self.exist: 134 #クラスEnemyBulletのインスタンス生成 135 enemybullet = EnemyBullet(self.x, self.y) 136 #クラスEnemyBulletのメソッドdraw 137 enemybullet.draw() 138 #クラスEnemyBulletのメソッドshoot 139 enemybullet.shoot() 140 141 def move(self): 142 global value 143 144 if self.exist: 145 if value % 2 == 0: 146 #self.x += Enemy_Move_Space_X 147 print('0') 148 #time.sleep(1) 149 value += 1 150 else: 151 #self.x -= Enemy_Move_Space_X 152 print('1') 153 #time.sleep(1) 154 value += 1 155 156 #画像位置の変更 157 cv.coords(self.id, self.x, self.y) 158 #処理を遅らせる 159 root.after(1000, Enemy.move) 160 161 def destroy(self): 162 #画像の消去 163 cv.delete(self.id) 164 165#敵の弾のクラス 166class EnemyBullet: 167 #クラスのインスタンス作成時に起動するメソッド 168 def __init__(self, x, y): 169 self.x = x 170 self.y = y 171 172 def draw(self): 173 #長方形の生成 174 self.id = cv.create_rectangle(self.x-Bullet_Width, self.y+Bullet_Height, self.x+Bullet_Width, self.y-Bullet_Height,fill="red") 175 176 def shoot(self): 177 if self.y <= Window_Height: 178 #画像の移動 179 cv.move(self.id, 0, Bullet_Height) 180 self.y += Bullet_Height 181 #同じクラスのメソッドcollision 182 self.collision() 183 #処理を遅らせる 184 root.after(Bullet_Speed, self.shoot) 185 186 def collision(self): 187 if ((self.x-cannon.x)**2+(self.y-cannon.y)**2) < Collision_Detection: 188 #gameoverメソッド 189 gameover() 190 191 def destroy(self): 192 #画像の消去 193 cv.delete(self.id) 194 195def gameclear(): 196 winflag = 0 197 for enemy in enemies: 198 #敵を倒すたびに数が+1される 199 if enemy.exist == False: 200 winflag += 1 201 202 #倒した敵の数が敵の総数と同じ場合 203 if winflag == Number_Of_Enemy: 204 #good!のテキストを削除 205 cv.delete("good") 206 #Congratulation!テキストの作成 207 cv.create_text(Window_Width//2, Window_Height//2-80, text="Congratulation!",fill="lime", font=("System", Text_Congratulations_Size)) 208 #GameClear!テキストの作成 209 cv.create_text(Window_Width//2, Window_Height//2+20, text="GAME CREAR!", fill="lime", font=("System", Text_GameClear_Size)) 210 211def gameover(): 212 #画像cannon, goodの削除 213 cv.delete("cannon", "good") 214 #GameOverテキストの作成 215 cv.create_text(Window_Width//2, Window_Height//2, text="GAME OVER", fill="red", font=("System", Text_GameOver_Size)) 216 217def enemy_randomshoot(): 218 #ランダムに配列enemiesから選ぶ 219 enemy = random.choice(enemies) 220 #メソッドenemy_shoot 221 enemy.enemy_shoot() 222 #処理を遅らせる 223 root.after(Enemy_Shoot_Interval, enemy_randomshoot) 224 225def numberplus(): 226 global value 227 value = value + 1 228 229if __name__ == '__main__': 230 #初期画面の作成 231 root = tk.Tk() 232 #タイトルの設定 233 root.title('shootingNeo') 234 #キャンバスの作成 235 cv = tk.Canvas(root, width=Window_Width, height=Window_Height, bg='black') 236 #キャンバスの設置 237 cv.pack() 238 239 #砲台の画像の読み込み 240 cannon_Image = tk.PhotoImage(file="canon.png") 241 #敵の画像の読み込み 242 crab_Image = tk.PhotoImage(file="crab.png") 243 244 #メニューバーの作成 245 menubar = tk.Menu(root) 246 #ウィンドウの属性を変更 247 root.configure(menu=menubar) 248 #ウィンドウに子メニューを追加・設定 249 menubar.add_command(label="Quit", underline=0, command=root.quit) 250 251 #クラスCannonのインスタンスを生成 252 cannon = Cannon(Window_Width//2, Cannon_Y) 253 254 #enemy = Enemy() 255 #root.after(1000, enemy.move) 256 257 #for文の中を回すための配列 258 enemies = [] 259 260 for i in range(Number_Of_Enemy): 261 enemy_i = Enemy(i*Enemy_Space_X+50, Enemy_Space_Y) 262 enemies.append(enemy_i) 263 264 #root.after(1000, Enemy.move) 265 266 #GUIアプリの表示 267 root.mainloop()
となります。問題のRoopメソッドが名前は変わりますが141行目のEnemyクラスのmoveメソッドです。
メソッドを呼び出している行が126行目、159行目となります。
※こちらのソースコードはサイト様(https://qiita.com/ell/items/f0f74865c07710f1eab8
)を参考にしていろいろと改変して練習しているものです。
※コメントアウトされているコードは試行錯誤したものが残っているものです。重要性は低いです。
回答2件
あなたの回答
tips
プレビュー