为什么在tkinter中每次显示新图像时,此级别中的计时器会变得更快?

huangapple go评论73阅读模式
英文:

Why does the timer in this level go faster each time a new image is shown in tkinter?

问题

这是您的代码的中文翻译部分:

def medium_level():
  global score2,current_image2, total_games,total_w
  total_games+= 1
  current_image2 =0
  score2 = 0
  new = Toplevel(window)
  new.title("Medium Mode")
  new.configure(background=bg2)
  new.geometry("600x500")
  
  ans=tk.Entry(new,font=('Times', 25))
  ans["justify"] = "center"
  ans["borderwidth"] = "1px"
  ans.place(x=90,y=270,width=414,height=188)

  rules2=tk.Label(new, font=('Times', 20),bg=bg2)
  rules2["text"] = "Enter Country Name Here:"
  rules2["justify"] = "center"
  rules2.place(x=110,y=230)

  timelbl=tk.Label(new, text="Time: ",font=('Times', 15),bg=bg2)
  timelbl.place(x=480,y=50)
  
  score_label = tk.Label(new, text="Score: 0"+"/12", font=('Times', 15),bg=bg2)
  score_label.place(x=40, y=50)

  image_label = tk.Label(master=new)
  image_label.place(relx=0.30, rely=0.10)
  
  image_files = ['bangladesh.png', 'germany.png', 'turkey.png', 'egypt.png', 'madagascar.png','ecuador.png','croatia.png','palestine.png','south africa.png','mongolia.png','peru.png','vietnam.png']
  random.shuffle(image_files)
  
  def next_image2():
      global current_image2, countdown
      if current_image2 < len(image_files):
          # 获取下一张图像并显示
          image_path = image_files[current_image2]
          image = tk.PhotoImage(file=image_path)
          image_label.configure(image=image)
          image_label.image = image

          current_image2 += 1
          countdown = 20
          start_timer()
          timelbl.config(text=f"Time: {countdown}")
          
      else:
          # 显示最终得分
          messagebox.showinfo("Game Over", f"Your score is: {score2}"+"/12")
          new.quit()

  def start_timer():
      global countdown
      countdown = 20
      update_timer()

  def update_timer():
      global countdown
      timelbl.config(text=f"Time: {countdown}")

      if countdown == 0:
          # 时间到,移动到下一张图像
          next_image2()
      else:
          countdown -= 1
          new.after(1000, update_timer)
  
  def check_answer2(event):
      global score2,total_w,countdown,update_timer
      # 从输入框获取用户答案
      user_answer = ans.get().strip().lower()

      # 获取当前图像的正确答案
      correct_answer = image_files[current_image2 - 1].split('.')[0].lower()

      # 检查用户答案是否正确
      if user_answer == correct_answer:
          score2 += 1
          total_w+=1
          score_label.config(text=f"Score: {score2}"+"/12")

      # 清空输入框
      ans.delete(0, tk.END)

      # 移动到下一张图像
      next_image2()

  # 将check_answer函数绑定到回车键按下事件
  ans.bind('<Return>', check_answer2)
  next_image2()

这是您尝试的一种方式:

  def start_timer():
      global countdown
      countdown = 20
      update_timer()

  def update_timer():
      global countdown
      timelbl.config(text=f"Time: {countdown}")

      if countdown == 0:
          # 时间到,移动到下一张图像
          next_image2()
      else:
          countdown -= 1
          new.after(1000, update_timer)

但是,无论我尝试了什么,计时器的速度似乎只会变得更快。

如果您的计时器速度越来越快,可能是因为您的计时器在每次显示新图像时都会被重置,但您的 update_timer 函数也在每次新图像显示时被调用。这意味着您的计时器会以更高的速度递减,因为它实际上在进行多次计数。

为了解决这个问题,您可以尝试将 update_timer 函数的调用移到 start_timer 函数内部,以确保在每次新图像显示时只启动一个计时器。这应该防止计时器速度越来越快的问题。

例如:

  def start_timer():
      global countdown
      countdown = 20
      update_timer()

  def update_timer():
      global countdown
      timelbl.config(text=f"Time: {countdown}")

      if countdown == 0:
          # 时间到,移动到下一张图像
          next_image2()
      else:
          countdown -= 1
          new.after(1000, update_timer)

  # 在next_image2函数内部调用start_timer来启动计时器
  def next_image2():
      global current_image2, countdown
      if current_image2 < len(image_files):
          # 获取下一张图像并显示
          image_path = image_files[current_image2]
          image = tk.PhotoImage(file=image_path)
          image_label.configure(image=image)
          image_label.image = image

          current_image2 += 1
          countdown = 20
          start_timer()
          timelbl.config(text=f"Time: {countdown}")
          
      else:
          # 显示最终得分
          messagebox.showinfo("Game Over", f"Your score is: {score2}"+"/12")
          new.quit()

这样,每次新图像显示时,都会启动一个新的计时器,并且计时器速度不会越来越快。

英文:

For my game, when a new flag is shown each time after the user clicks enter or the timer goes to zero, the timer is supposed to reset back to 20 which it does but, it goes down even faster each time the new image is shown. How do I make it so that it goes down only 1 second each time and doesn't get faster?

Here is the code to the full level:

def medium_level():
global score2,current_image2, total_games,total_w
total_games+= 1
current_image2 =0
score2 = 0
new = Toplevel(window)
new.title(&quot;Medium Mode&quot;)
new.configure(background=bg2)
new.geometry(&quot;600x500&quot;)
ans=tk.Entry(new,font=(&#39;Times&#39;, 25))
ans[&quot;justify&quot;] = &quot;center&quot;
ans[&quot;borderwidth&quot;] = &quot;1px&quot;
ans.place(x=90,y=270,width=414,height=188)
rules2=tk.Label(new, font=(&#39;Times&#39;, 20),bg=bg2)
rules2[&quot;text&quot;] = &quot;Enter Country Name Here:&quot;
rules2[&quot;justify&quot;] = &quot;center&quot;
rules2.place(x=110,y=230)
timelbl=tk.Label(new, text=&quot;Time: &quot;,font=(&#39;Times&#39;, 15),bg=bg2)
timelbl.place(x=480,y=50)
score_label = tk.Label(new, text=&quot;Score: 0&quot;+&quot;/12&quot;, font=(&#39;Times&#39;, 15),bg=bg2)
score_label.place(x=40, y=50)
image_label = tk.Label(master=new)
image_label.place(relx=0.30, rely=0.10)#, relheight=0.5, relwidth=0.5)
image_files = [&#39;bangladesh.png&#39;, &#39;germany.png&#39;, &#39;turkey.png&#39;, &#39;egypt.png&#39;, &#39;madagascar.png&#39;,&#39;ecuador.png&#39;,&#39;croatia.png&#39;,&#39;palestine.png&#39;,&#39;south africa.png&#39;,&#39;mongolia.png&#39;,&#39;peru.png&#39;,&#39;vietnam.png&#39;]
random.shuffle(image_files)
def next_image2():
global current_image2, countdown
if current_image2 &lt; len(image_files):
# Get the next image and display it
image_path = image_files[current_image2]
image = tk.PhotoImage(file=image_path)
image_label.configure(image=image)
image_label.image = image
current_image2 += 1
countdown = 20
start_timer()
timelbl.config(text=f&quot;Time: {countdown}&quot;)
else:
# Show the final score
messagebox.showinfo(&quot;Game Over&quot;, f&quot;Your score is: {score2}&quot;+&quot;/12&quot;)
new.quit()
def start_timer():
global countdown
countdown = 20
update_timer()
def update_timer():
global countdown
timelbl.config(text=f&quot;Time: {countdown}&quot;)
if countdown == 0:
# Time&#39;s up, move to the next image
next_image2()
else:
countdown -= 1
new.after(1000, update_timer)
def check_answer2(event):
global score2,total_w,countdown,update_timer
# Get the user&#39;s answer from the entry box
user_answer = ans.get().strip().lower()
# Get the correct answer for the current image
correct_answer = image_files[current_image2 - 1].split(&#39;.&#39;)[0].lower()
# Check if the user&#39;s answer is correct
if user_answer == correct_answer:
score2 += 1
total_w+=1
score_label.config(text=f&quot;Score: {score2}&quot;+&quot;/12&quot;)
# Clear the entry box
ans.delete(0, tk.END)
# Move to the next image
next_image2()
# Bind the check_answer function to the Return key press event
ans.bind(&#39;&lt;Return&gt;&#39;, check_answer2)
next_image2()

This is one of the ways I have tried:

  def start_timer():
global countdown
countdown = 20
update_timer()
def update_timer():
global countdown
timelbl.config(text=f&quot;Time: {countdown}&quot;)
if countdown == 0:
# Time&#39;s up, move to the next image
next_image2()
else:
countdown -= 1
new.after(1000, update_timer)

But, for every thing I try the speed of the timer just gets faster

答案1

得分: 1

这是因为在启动新的倒计时时,您没有取消现有的 countdown

after_id = None   # 初始化全局的 after ID

def medium_level():
    ...
    def start_timer():
        global countdown, after_id # .after() 返回的 ID
        countdown = 20
        # 如果存在 after ID,则取消现有的 after 循环
        if after_id:
            new.after_cancel(after_id)
            after_id = None
        update_timer()

    def update_timer():
        global countdown, after_id
        timelbl.config(text=f"时间:{countdown}")

        if countdown == 0:
            # 时间到,转到下一张图片
            next_image2()
        else:
            countdown -= 1
            # 保存 after ID
            after_id = new.after(1000, update_timer)
   ...
英文:

It is because you do not cancel the existing countdown when starting new countdown.

after_id = None   # initialize the global after ID

def medium_level():
    ...
    def start_timer():
        global countdown, after_id # ID returned by .after()
        countdown = 20
        # cancel existing after loop if any
        if after_id:
            new.after_cancel(after_id)
            after_id = None
        update_timer()

    def update_timer():
        global countdown, after_id
        timelbl.config(text=f&quot;Time: {countdown}&quot;)

        if countdown == 0:
            # Time&#39;s up, move to the next image
            next_image2()
        else:
            countdown -= 1
            # save the after ID
            after_id = new.after(1000, update_timer)
   ...

huangapple
  • 本文由 发表于 2023年6月12日 08:41:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定