2015-06-18 2 views
-1

SO Я использую Python 3.4 и tkinter.Ярлык продолжает появляться

И когда я снова вызываю функцию снова n, которая содержит метку, метка продолжает появляться в окне, но предыдущая метка не исчезает?

Как удалить любую напечатанную метку из окна графического интерфейса, как только функция вызывается, а затем отображать новую?

Вот код: -

#def prestart(): 
    #here I check if number of match is okay, if not, user is redirected to setting else, I call start() 

def start(): 

    #CPU Choice 
    cpu_choice = Label(historyframe, text = "CPU Choosed: {}".format(dict['cpu_choice'])) 

    #Played Match 
    #played_num_of_match = Label(scoreframe, text = "Number of Matches Played: {}".format(int(dict['match_played']))) 

    #Display Status 
    status_disp = Label(scoreframe, text = "Current Status: {}".format(dict['status'])) 

    if(int(dict['match_played']) < int(dict['num_of_match'])): 
     playframe.grid(row = 1, column = 0) 
     historyframe.grid(row = 2, column = 1) 
     status_disp.pack(fill=X) 
    elif(int(dict['match_played']) == int(dict['num_of_match'])): 
     playframe.grid(row = 1, column = 0) 
     historyframe.grid(row = 2, column = 1) 
     status_disp.pack(fill=X) 
     cp = dict['cpu_point'] 
     up = dict['user_point'] 
     result(cp, up) 
    cpu_choice.pack(fill = X) 
    scoreframe.grid(row = 2, column = 0) 

Эта функция только обновляет экран!

def send_value(x): 
    #Here I run logic of game and change value of key in dictionary and call start() at end of change. 

Теперь кнопки выбора не имеют какого-либо определения, так как их не нужно снова называть n. Я просто заставляю playframe исчезать. Вот код для них: -

#Display Question 
question = Label(playframe, text = "Rock? Paper? Scissor?") 

#Rock 
rock = Button(playframe, text = "Rock!", command = lambda: send_value("ROCK")) 

#Paper 
paper = Button(playframe, text = "Paper!", command = lambda: send_value("PAPER")) 

#Scissor 
scissor = Button(playframe, text = "Scissor!", command = lambda: send_value("SCISSOR")) 

Так что, когда пользователь нажимает кнопку Рок/Бумага/Scissor, я просто изменить значение ключа в словаре! Но если я сохраню функцию внешней метки, она не будет автоматически обновляться!

Все остальное работает отлично. Я сейчас начну делать код чище.

+1

Почему бы просто не обновить текст в существующей этикетке? Также покажите код. –

+0

Вы просто пытаетесь обновить ярлык? Почему вы создаете его внутри функции? – maccartm

+0

Пожалуйста, покажите нам MCVE, который иллюстрирует проблему. –

ответ

1

Попробуйте что-то вроде этого вместо того, чтобы создавать новую метку каждый раз, когда:

import Tkinter as tk 

class Window(): 

    def __init__(self, root): 

     self.frame = tk.Frame(root) 
     self.frame.pack() 

     self.i = 0 
     self.labelVar = tk.StringVar() 
     self.labelVar.set("This is the first text: %d" %self.i) 

     self.label = tk.Label(self.frame, text = self.labelVar.get(), textvariable = self.labelVar) 
     self.label.pack(side = tk.LEFT) 

     self.button = tk.Button(self.frame, text = "Update", command = self.updateLabel) 
     self.button.pack(side = tk.RIGHT) 

    def updateLabel(self): 

     self.i += 1 
     self.labelVar.set("This is new text: %d" %self.i) 


root = tk.Tk() 
window = Window(root) 
root.mainloop() 

Важные моменты:

1) используется класс, так как это намного проще передавать значения вокруг, когда все объекты и переменные Tkinter являются переменными-членами, доступными из всех ваших функций графического интерфейса.

2) updateLabel не создает новую метку. Он просто обновляет объект StringVar() для хранения нового текста при каждом вызове функции. Это достигается с помощью ключевого слова textvariable = self.labelVar при создании виджета «Ярлык».

PS: Это делается в Python 2.5 так для этого кода, чтобы работать для вас, изменить Tkinter к tkinter

EDIT 06/19/2015:

Если вы хотите реализуйте что-то похожее на то, что у меня есть с вашим кодом, без, используя класс, вам нужно будет передать ссылки на ваши переменные.

1) Изменение start:

этикетки cpu_choice, status_disp и т.д., должны быть созданы вне функции; вероятно, в том же месте, что и question, rock, paper, scissors и т. д. Вы также упакуете их вне функции. То же самое со всеми вызовами .grid внутри start; вам не нужно звонить pack или grid более одного раза: сразу при создании виджета.

следующие строки:

playframe.grid(row = 1, column = 0) 
    historyframe.grid(row = 2, column = 1) 
    status_disp.pack(fill=X) 

Может быть сделано за пределами функции, а также; вы выполняете эти 3 оператора как при if, так и в условиях elif. Это означает, что они не являются условными утверждениями; они выполняются независимо от действительности условия.

2) Создание StringVar как для cpu_choice & status_disp & редактировать Ярлыки следующим образом (помните, за пределами функции):

cpu_choice_text = StringVar() 
    cpu_choice_text.set("Set this to whatever is shown at the start of the game") 
    cpu_choice = Label(historyframe, text = cpu_choice_text.get(), textvariable = cpu_choice_text) 
    cpu_choice.pack(fill = X) 

    # And do this same thing for status_disp 

3) Когда вы звоните start, вы теперь передать его cpu_choice_text & status_disp_text (или то, что они называются). Вместо того, чтобы пытаться изменить поле text рамки Label, вы можете теперь использовать вызов set на StringVar, который подключен к этикетке &. Этикетка будет автоматически обновляться. Пример:

def start(cpu_choice_text, status_disp_text): 
     cpu_choice.set(text = "CPU Choice: {}".format(dict['cpu_choice'])) 
     ... 

В качестве альтернативы, завернуть все это в классе и сделать это намного проще для себя с помощью self на каждой Tkinter переменной & виджета. Таким образом, вам не нужно передавать переменные в свои функции, просто получайте переменные-члены напрямую, как у меня с self.i, self.labelVar в моем примере.

+2

Еще лучше, вы можете удалить использование 'StringVar' и напрямую обновить ярлык. Это еще один объект, с которым вам нужно справиться. –

+0

Пожалуйста, проверьте код @BryanOakley –

+0

Я использовал команду .set и .get. Я нашел его раньше, но с помощью кода я понял, как его использовать. Но я не создаю класс. С какими проблемами я могу столкнуться? –

0

Каждый раз, когда вы звоните start, вы создаете новые ярлыки и используйте grid, чтобы разместить их в том же месте, что и старые ярлыки. Лучшим решением является создание только однократных меток, но если вы настаиваете на создании новых ярлыков каждый раз, когда вызывается start, сначала нужно удалить старые метки.

Вы можете использовать метод метки, чтобы уничтожить его, но для этого вам необходимо сохранить глобальную ссылку на метку.

+0

Мне очень нравится, что сделал maccartm. Но ИДК как реализовать его в данный момент. Я сейчас работаю над этим. Думаю, я понимаю, что вы имеете в виду. Я дам ему попробовать. Потому что я думаю, что я уже пробовал это. –

+0

Это не работает. После уничтожения я не могу перезвонить! –

Смежные вопросы