Как сделать так, чтобы в tkinter не пропускался ордер «bind»? - PullRequest
3 голосов
/ 27 апреля 2019

Я пытаюсь создать игру, используя tkinter, в которой игроки вводят свои имена в виджет входа.

После ввода своего имени пользователь должен нажать клавишу ввода, чтобы вызвать функцию «имена_плееров», которая в идеале сохранит имя игрока в списке, удалит текст в виджете ввода и затем перейдет к следующему циклу (т.е. игрок).

Сценарий, кажется, игнорирует привязку и перемещается прямо к строке "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 ]

2 голосов
/ 28 апреля 2019

Entry не работает как input(), он не остановит код и не будет ждать, пока вы не введете текст и не нажмете ввод. 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()

Так же, как он работает в других графических интерфейсах (не только в tkinter) и других языках (не только в Python)

0 голосов
/ 28 апреля 2019

Мое представление о том, что вы пытаетесь сделать, должно быть таким же, чтобы принимать данные от игрока один за другим, пока все игроки не добавят имя. Проблема с вашим кодом - for, он должен завершаться без участия игрока (технически), поэтому я выбрал механизм обновления, который есть у tkinter, когда значение изменяется в winget, которое будет обновляться самостоятельно. привязать к кнопке значение изменения с шагом. Если вы хотите повторно использовать i, укажите его в начале def того же числа

Этот пример работает, ввод initialise_game такой же, как и раньше, замена конде в середине будет работать нормально, кроме случаев, когда ваш код использует .grid(), затем замените ask_name.pack()

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...