如何确保在tkinter中不跳过“绑定”顺序?

时间:2019-04-27 18:09:18

标签: python-3.x tkinter

我正在尝试使用tkinter创建一个游戏,在该游戏中,玩家将其姓名输入到条目小部件中。

输入名称后,用户应按Enter键以调用“ player_names”功能,理想情况下,该功能会将玩家名称保存在列表中,删除条目小部件中的文本,然后继续进行下一个循环(即玩家) 。

该脚本似乎正在忽略绑定,而直接移至“ self.name_entry.destroy()”行。如何确保脚本在继续之前先等待命令?

def initialise_game(self, num_of_players):

    self.players_list = []
    for i in range(num_of_players):
        player_num = i+1
        self.name_label = tk.Label(self.bg_label, text='What is the name'
                                   ' of Player ' + str(player_num) + '?')
        self.name_label.grid(row=0, padx=200, pady=120)

        self.name_entry = tk.Entry(self.bg_label)
        self.name_entry.grid(row=1, padx=200, pady=0)
        self.name_entry.bind('<Return>', self.player_names)

    self.name_entry.destroy()


def player_names(self, event):
    self.players_list.append(self.name_entry.get())
    self.name_entry.delete(0, 'end')

2 个答案:

答案 0 :(得分:2)

Entry不能像input()那样工作,它不会停止代码并等待您输入文本并按Enter。 GUI创建Entry,并在Entry之后立即执行代码。您有bind来分配要按Enter键执行的功能,该功能应从Entry中获取值,并替换小部件(或仅Label中的文本)。它还应该删除最后一个玩家之后的Entry,以便您必须计算执行功能的次数(或已经拥有多少玩家-self.player_num

我没有测试这段代码,但是应该可以。

def initialise_game(self, num_of_players):

    self.players_list = []

    # remeber values in class variables, not local one
    self.num_of_players = num_of_players
    self.player_num = 0

    # create only one Label - and change text in it
    self.name_label = tk.Label(self.bg_label,
    self.name_label.grid(row=0, padx=200, pady=120)

    # create only one Entry and assign function `self.player_names`
    self.name_entry = tk.Entry(self.bg_label)
    self.name_entry.grid(row=1, padx=200, pady=0)
    self.name_entry.bind('<Return>', self.player_names)

    # set text for first player
    self.player_num += 1
    self.name_label["text"] = 'What is the name of Player {} ?'.format(player_num)

def player_names(self, event):

    # get player's name from Entry                                    
    self.players_list.append(self.name_entry.get())
    self.name_entry.delete(0, 'end')

    # set text for next player or destroy Entry after last player
    self.player_num += 1
    if self.player_num <= self.num_of_players:
        self.name_label["text"] = 'What is the name of Player {} ?'.format(player_num)
    else:
        self.name_label.destroy()                               
        self.name_entry.destroy()

与在其他GUI(不仅适用于tkinter)和其他语言(不仅适用于Python)中使用的方式相同

答案 1 :(得分:0)

我对您要完成的目标的想法应该是相同的,从一位玩家开始逐个输入直到所有玩家都添加了名字。 代码的问题是for,它需要在没有玩家输入的情况下变得精打细算(技术上),指示我选择了tkinter拥有的更新机制,并在winget中更改了值,winget将会更新自身我将按钮的增量更改为绑定值。 如果您想重用i,请将其引用为def的开头

此示例有效,initialise_game的输入与之前相同,替换中间的conde效果很好,除非您的代码使用.grid()然后替换ask_name.pack() < / p>

import tkinter as tk

root = tk.Tk()
root.bg_label = tk.Frame(root)

# Added code, top and bottom are for testing
#--------------------------------------------------------------------------------

root.players_list = []  # Global variabe witch can be accesd by all funcions

i = 1 # This global value is to keep a clear reference on the count of windows
def initialise_game(self, num_of_players): 
    ask_name = tk.Frame(self)
    L = tk.Label(ask_name, text=('What is the name of Player ' + str(i) + '?'))
    L.grid(row=0, padx=200, pady=120)
    E = tk.Entry(ask_name)
    def modify_entry(NULL):
        root.players_list.append(E.get())
        E.delete(0, 'end')
        global i # Change the "search" of values to outside the funtion
        i += 1
        L.config(text=('What is the name of Player ' + str(i) + '?'))
        if (i > num_of_players): # Close the Frame wen all were answered
            root.players_list.append(E.get())
            ask_name.destroy()
    E.bind('<Return>', modify_entry)
    E.grid(row=1, padx=200, pady=0)
    ask_name.pack() # You can replace it with grin , this moves the Label + Entry were u want

#--------------------------------------------------------------------------------

initialise_game(root.bg_label, 3)
root.bg_label.pack()
root.mainloop()