Обновлять / обновлять фрейм обратного отсчета всякий раз, когда он вызывается функцией tkraise () в tkinter - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь создать приложение обратного отсчета за 2 минуты с несколькими окнами.Я помещаю все окна (фреймы) в основной контейнер, а затем использую tkraise (), чтобы поднять фрейм при каждом нажатии навигационной кнопки в определенном окне (например, фрейм 'startPage' будет поднят, если кнопка 'back to startPage'щелкнул).Приведенный ниже код хорошо работает только при первом создании объекта класса PracticePage.Тем не менее, таймер все еще работает сзади, когда я перемещаюсь от фрейма обратного отсчета (класс PracticePage) к другой странице.Другими словами, таймер не будет отсчитывать от 2 минут, когда я перехожу с другой страницы обратно на страницу таймера обратного отсчета.Я хочу, чтобы он отсчитывал от 2 минут всякий раз, когда поднимается кадр таймера.Я новичок в программировании.Я извинился, если мой вопрос и код сбивают с толку.Может кто-нибудь помочь?Заранее спасибо.

Ниже мой код:

import tkinter as tk
from tkinter import *
from tkinter import ttk
import time

class App(tk.Tk):   #we want this class to inherit from tk.Tk
    def __init__(self, *args, **kwargs):  
        tk.Tk.__init__(self, *args, **kwargs)

        tk.Tk.wm_title(self,"PreSys")

        container = tk.Frame(self, height = 1000, width =1000)
        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (SignInPage, StartPage, PracticePage):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(SignInPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()   #to raise one of the frames up to the front    


class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)


        self.startButton = ttk.Button(self, text="スタート", command = lambda: controller.show_frame(PracticePage))

        self.startButton.pack()

class PracticePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.timeLeft = tk.Label(self,text= "")
        self.backButton = ttk.Button(self, text="やり直す", command = lambda: controller.show_frame(StartPage))
        self.homeButton = ttk.Button(self, text="サインアウト", command = lambda: controller.show_frame(SignInPage))

        self.timeLeft.pack()
        self.backButton.pack()
        self.homeButton.pack()
        #rc.start_record(SignInPage.entry_name.get())

        self.remaining = 0
        self.countdown(121)

    def countdown(self, remaining = None):
        if remaining is not None:
            self.remaining = remaining

        if self.remaining <= 0:
            self.timeLeft.configure(text="お疲れ様です!")
        else:
            mins, secs = divmod(self.remaining,60)
            mins = round(mins)
            secs = round(secs)
            self.timeLeft.configure(text=str(mins) +"分"+ str(secs) +"秒")
            self.remaining = self.remaining - 1
            self.after(1000, self.countdown)

apps = App()
apps.mainloop()

1 Ответ

0 голосов
/ 17 ноября 2018

Прежде чем мы перейдем к решению, когда вы предоставляете свой код, убедитесь, что оно работает.Вы удалили SignInPage, потому что в этом не было необходимости, но вы не отслеживали и не удаляли другие ссылки на него (например, - self.show_frame(SignInPage) в App.__init__ и self.homebutton в PracticePage.

Что касается вашей проблемы со сбросом таймера, есть много способов сделать это, но все они сводятся к тому, что все, что вы делаете, это поднимает фреймы: вы не включаете никакого кода, который влияет на countdownна каком кадре вы сейчас переключаетесь.

Поскольку это относительно простое приложение, я предложу самое простое решение: когда вы поднимаете PracticePage, сбрасываете переменную remaining.по мере возможности, мы просто изменим show_frame

## You should store variables that are meaningful (you can place this underneath the imports)
PRACTICETIME = 121

## App():
    def show_frame(self, cont):
        frame = self.frames[cont]
        if cont == PracticePage:
            frame.remaining = PRACTICETIME
        frame.tkraise()   #to raise one of the frames up to the front

В более крупном приложении я бы порекомендовал либо использовать widget.after_cancel(), чтобы полностью остановить обратный отсчет, либо просто уничтожить и воссоздать Pages, если это целесообразноДля этого метода вы можете заметить задержку в 1 секунду, когда PracticePage по-прежнему отображает предыдущее время remaining: если это действительно вас беспокоит, то я бы порекомендовал extизменение кода, который форматирует PracticePage.timeLeft, в свою собственную функцию, а затем вызов этой функции из App.show_frame сразу после установки remaining.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...