当前位置: 代码迷 >> python >> 函数未调用以及如何在 tkinter 循环中等待单击
  详细解决方案

函数未调用以及如何在 tkinter 循环中等待单击

热度:84   发布时间:2023-06-13 16:52:19.0

我现在遇到了死胡同 - 首先,当您单击一个动态按钮时,会进行函数调用,并且它确实返回所单击按钮的名称。 然而,它应该调用的fEndDay函数似乎没有运行。

编辑:这一天正在运行。 刚刚重新启动了 Liclipse,它开始工作了。 没有解释。 但是,按钮等待问题仍然存在。

我现在也有点卡住了。 本质上我想要:

  • 而当日 < 总天数....
    • 运行每日事件,更新屏幕对象。
    • 通过单击按钮进行选择。
    • 增加当前日期。

但是,日循环会停止显示屏幕(即处理循环)。 我想如果有代码将对象显示向上推并处于无限循环中,该循环被按钮单击破坏,那就可以了。 其他想法? 下面的当前代码。

#!/usr/bin/python

# Reminder to self - lots to add. Include a function to reset the text content
# and populate with day number, score summary etc as a template. We can then
# add to it.



#################### IMPORT MODULES WE NEED ############################
import time                     # For sleep delays
from random import randint      # for random numbers
from _ast import While          # while loops
import tkinter as Tkinter       # this one handles windows and buttons etc
from tkinter import *           # skip the tkinter prefix (constants etc)
# import tkmessagebox  # Python 2 alternative!
from tkinter import messagebox as tkMessageBox # Python 3
import sys                      # for quit when added ie  sys.exit()  
from functools import partial   # So we can create lists of buttons & commands
import time                     # threading support - check events while waiting
import concurrent.futures       # threading - think i'll be needing all this





################## CREATE A NEW CLASS (CONTAINER) ############################
class CrazyCoder (Tkinter.Tk):
    # When the class is created, the function fInitialise is run, below.
    def __init__(self,parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.fInitialize()  # State here any functions to run on creation





    ################################ FUNCTION ################################
    # Set up variables etc...
    def fInitialize(self):


        ########################### VARIABLES ###############################
        # Overkill here probably but will revisit later! Listed / initialised  
        # here to simplify searching later on!
        # Could pass most of theses but will keep it simple and update globally
        # to start with
        self.vDayNumber = 1     # What the current day is
        self.vFinalDay = 10     # The last day of our game
        self.vPlayerName = ''   # To hold the players name
        self.vGameName = ''     # To hold the game name
        self.vChoice = ''       # To hold the user choices clicked
        self.vRandom = 0        # To hold random numbers!
        self.vGameplay = 0      # SCORES: Current gameplay score
        self.vGraphics = 0      # SCORES:  Current graphics score
        self.vSound = 0         # SCORES:  current sound score
        self.vBugs = 0          # SCORES:  current bug score'
        self.vBackColor = 'grey'    # The background colour of our app
        self.vDynamic_Buttons = []  # To hold button objects each "screen"
        self.vEntryBox = []         # To hold text entry box objects
        self.vTextEntry = ''        # Stores user text entry value temporarily
        self.vAvailableButtons = [] # To hold a list of AVAILABLE buttons/event


        ########################## APP SETUP ################################
        self.title('Crazy Coder')                # set window title
        self.geometry("500x500")                    # set screen size
        self.configure(background=self.vBackColor)  # set background colour

        # Add a "Title box"
        self.vTitle = Tkinter.Label(self,text='Crazy Coder')
        self.vTitle.configure(background=self.vBackColor)
        self.vTitle.pack(side=TOP,padx=10,pady=10)

        # Add a picture box (gif supported)
        self.vImage =     PhotoImage(file="PUG.gif")
        self.vPicture=Label(self,image=self.vImage)
        self.vPicture.image=self.vImage
        self.vPicture.pack()

        # Add the main text box 
        self.vMessageText = '''
        This is where your day number goes
        Scores go here too
        Event details go here too'''
        self.vMessage = Tkinter.Label(self,text=self.vMessageText)
        self.vMessage.configure(background=self.vBackColor) 
        self.vMessage.pack(side=TOP,padx=10,pady=10)


        # While loop does not work - there is no concept of
        # "display current buttons / screen and wait for click event"

        #while self.vDayNumber <= self.vFinalDay:

        self.vChoice = '' # Clear it ready to take a user choice each day

        print('DEBUG: On Main screen, starting now')    


        self.vRandom = randint(1,100)

        if self.vDayNumber == 1:
            self.fWelcomeScreen()   # Set up the welcome screen
        elif self.vRandom >= 0:
            self.fEvent1()          # Kick off event 1







    ############################# FUNCTION ################################# 
    # Sets the message on the main text box to whatever you put in brackets
    def fSetText(self,TextMessage):
        global vMessageText                 
        self.vMessageText = TextMessage      
        self.vMessage['text'] = self.vMessageText # This updates the text box




    ############################# FUNCTION ################################# 
    # Sets the image on the main picture box to whatever you put in brackets
    def fSetImage(self,ImageName):
        global vImage
        self.vImage = PhotoImage(file=ImageName) # Example "PUG2.gif"
        self.vPicture['image']=self.vImage        # This updates the image box 




    ############################# FUNCTION ################################# 
    # Add a new Entry box to our screen. Supports multiple uses
    def fAddEntryBox(self):
        self.vNewBox = Entry(width=20)
        self.vEntryBox.append(self.vNewBox)
        self.vNewBox.pack(side=TOP,padx=10,pady=10)    
        self.vNewBox.focus()




    ############################# FUNCTION ################################# 
    # Remove the Entry Boxes
    def fDeleteEntryBoxes(self):
        for each_box in self.vEntryBox:
            each_box.destroy()




    ############################# FUNCTION ################################# 
    # Read from the requested box number, cutting off the Enter at the end 
    def fReadEntryBox(self,BoxNumber): #BoxNumber 0 is the first box, 1 next
        global vTextEntry
        vTextEntry=self.vEntryBox[BoxNumber].get()




    ############################# FUNCTION ################################# 
    # Handles the the day passing by
    def fEndDay(self):
        global vPlayerName, vDayNumber
        self.vDayNumber = self.vDayNumber + 1    
        print("This print isn't running either!")





    ############################# FUNCTION ################################# 
    # A simple step to take a choice from the user - used for button code below
    def fMakeChoice(self,value): 
        global vChoice, vDayNumber
        self.fEndDay()
        self.vChoice = value
        print('Just Clicked:',self.vChoice, "and it's day ", self.vDayNumber)
        print('But fEndDay should have just run and increased it to 2!')





    ############################# FUNCTION ################################# 
    # Add buttons to the screen, based on vAvailableButtons 
    def fAddButtons(self): 
        global vAvailableButtons # Shouldn't need this here but...
        for each_button in self.vAvailableButtons:
            # Important: the Lambda section takes the CURRENT value of the variable 
            # and stores is in the command string. Without it, all the buttons
            # when clicked would do the same as the last button created! daft eh.
            vNewButton = Tkinter.Button(self, text=each_button, command=lambda v=each_button: self.fMakeChoice(v))
            self.vDynamic_Buttons.append(vNewButton)
            vNewButton.pack(side= BOTTOM, padx = 10, pady = 10)





    ############################# FUNCTION ################################# 
    # Clear the buttons out ie before drawing new ones
    def fDeleteButtons(self):
        for each_button in self.vDynamic_Buttons:
            each_button.destroy()




    ############################# FUNCTION ################################# 
    # Pop up message box
    def fMessage(self,Message):
        self.tkMessageBox.showinfo("News", Message)    




    #*********************************************************************# 
    #*********************    EVENTS SECTION   ***************************# 
    #*********************************************************************# 
    # We'll define a function here for each "daily event"
    # The section will be responsible for:
    #    1) Updating the screen image (if necessary)
    #    2) Updating the text box content 
    #    3) Adding entry boxes and buttons as required
    #    4) Ending the day (there will be one decision per day for now)



    ############################# EVENT ################################# 
    # The welcome screen
    def fWelcomeScreen(self):
        global vAvailableButtons
        self.vTextMessage = '''
        Yawn. You wake up.
        Whats your name?
        '''
        self.fSetText(self.vTextMessage)
        time.sleep(1)   # delays for 1 second
        self.fAddEntryBox()  # Add an entry box for a name
        self.vAvailableButtons = ['Ok']
        self.fAddButtons()   # vChoice set on click, and day ended



    ############################# EVENT ################################# 
    # A random event
    def fEvent1(self):
        global vAvailableButtons
        self.vTextMessage = '''
        This is an event. What will you do?
        '''
        self.fSetText(self.vTextMessage)
        time.sleep(1)   # delays for 1 second
        self.vAvailableButtons = ['Ok']
        self.fAddButtons()   # vChoice set on click, and day ended




# Start the program    
if __name__ == "__main__":
    app = CrazyCoder(None)
    app.mainloop()

您希望每天运行一次函数这一事实与希望动画每秒运行 30 帧没有什么不同。 您实际上想要一个运行 1 fpd(每天一帧)的“动画”。

实现这一点的方法是创建一个每天运行一次的函数。

def do_once_a_day():
    ...

接下来,创建一个每天调用一次该函数的函数:

def call_daily(self):
    self.do_once_a_day()
    if self.vDayNumber <= self.vFinalDay:
        root.after(1000*60*60*24, self.call_daily)

这将导致每 24 小时调用一次do_once_a_day 然后,您可以在该函数中做任何您想做的事情。

  相关解决方案