2014-12-12 5 views
0

그래서 저는 계산을하기 위해 함수를 호출하는 프로그램을 만들고 있습니다. 그리고 입력을 변경하고 다시 계산하기위한 버튼이 있습니다.Python tkinter가 호출 스택을 증가시키고 있습니까?

계산이 완료되기 전에 버튼을 누르면 이전 값으로 돌아 가기 전에 새로운 값이 계산되고 출력됩니다. 기본적으로이 프로그램은 버튼을 누른 후 두 번째 계산을 완료 한 후 첫 번째 계산으로 돌아 오는 것을 제외하고는 원하는대로 처리합니다 (모든 변수 값이 반환 됨).

문제의 일반적인 회로도 : 변경 (그런데 몬티 카를로 시뮬레이션) 3. '이동' 4. 계산이 화면에 인쇄 5. 버튼을 입력 1. 루트 돌이 2. 값 입력 값 6. 새 계산이 화면에 출력됩니다. 7. 새 변수가 완료되면 이전 변수 값에 대한 계산이 완료 될 때까지 반환됩니다.

파이썬이 이전 변수 값으로 돌아 가지 않도록하는 방법이 있습니까? 내 희망은 메인 루프로 돌아가서 화면의 계산이 정확하도록하는 방법이 있다는 것입니다. 감사!

편집 : 여기 코드입니다 (죄송이 조금 길어 이것은 Tkinter를 내 처음) :

from tkinter import * 
from tkinter import ttk 
from random import * 
from statistics import * 
from math import * 

''' 
Prompt user for: number attacking with, number of defenders at each space 
Output: n approaching 100000 and error range approaching .3%, probabilities of next roll, probabilities of winning at each spot, average number of pieces lost & stddev,buttons for decreasing defender/attacker 

''' 

def reset(): 
    attacker_entry.delete(0,END) 
    for i in range(len(spaces_entry)): 
     spaces_entry[i].delete(0,END) 
    update_buttons() 

def update_buttons(*args): 
    buttons = [attacker_2,attacker_1,split_button,defender_1,defender_2] 
    try: 
     if int(attacker_entry.get()) > 1: 
      for button in buttons: 
       button['state'] = ['normal'] 
     elif int(attacker_entry.get()) == 1: 
      attacker_2['state'] = ['disabled'] 
      split_button['state'] = ['disabled'] 
     elif int(attacker_entry.get()) == 0: 
      for button in buttons: 
       button['state'] = ['disabled'] 
      return 
     if int(space1_entry.get()) > 1: 
      defender_2['state'] = ['normal'] 
     elif int(space1_entry.get()) == 1: 
      defender_2['state'] = ['disabled'] 
      split_button['state'] = ['disabled'] 
    except: 
     for button in buttons: 
      button['state'] = ['disabled'] 

def subtract(label,*args): 
    if label == "both": 
     label = "att def 1" 
    end = int(label[-1:]) 
    if "att" in label: 
     attacker_amount.set(int(attacker_entry.get()) - end) 
    if "def" in label: 
     space1.set(int(space1_entry.get()) - end) 
    if int(space1_entry.get()) == 0: 
     attacker_amount.set(int(attacker_entry.get()) - 1) 
     for i in range(len(spaces)): 
      try: 
       spaces[i].set(int(spaces_entry[i+1].get())) 
      except: 
       spaces[i].set("") 
       win_avgs[i].set("") 
       pieces_left[i].set("") 
       most_likely[i].set("")     
     space10.set("") 
    update_buttons() 
    go() 

def check_if_multiple(list1,list2): 
    if len(list1)>1 and len(list2)>1: 
     ret_val = 2 
    else: 
     ret_val = 1 
    return ret_val 

def set_rolls(total,limit): 
    list = [] 
    for i in range(total): 
     if len(list) < limit: 
      list.append(randrange(1,7)) 
    return list 

def go(*args): 
    update_buttons() 
    try: 
     attacker_total = int(attacker_entry.get()) 
    except: 
     return 

    defender_pieces_list = [] 
    for entry in spaces_entry: 
     try: 
      new_val = int(entry.get()) 
      if new_val == 0: 
       None 
      else: 
       defender_pieces_list.append(new_val) 
     except: 
      None 

    defender_total_spaces = len(defender_pieces_list) 
    attacker_total_original = attacker_total 

    total_trials = 10000 
    defender_losses = 0 
    attacker_losses = 0 
    first_round_defender_total_wins = 0 
    first_round_attacker_total_wins = 0 
    first_round_split_total = 0 

    space1_succ,space2_succ,space3_succ,space4_succ,space5_succ,space6_succ,space7_succ,space8_succ,space9_succ,space10_succ = [],[],[],[],[],[],[],[],[],[] 
    space1_all,space2_all,space3_all,space4_all,space5_all,space6_all,space7_all,space8_all,space9_all,space10_all = [],[],[],[],[],[],[],[],[],[] 

    succ_list = [space1_succ,space2_succ,space3_succ,space4_succ,space5_succ,space6_succ,space7_succ,space8_succ,space9_succ,space10_succ] 
    all_list = [space1_all,space2_all,space3_all,space4_all,space5_all,space6_all,space7_all,space8_all,space9_all,space10_all] 

    for trial in range(total_trials): 
     if trial%20 == 0: 
      for i in range(0,defender_total_spaces): 
       try: 
        win_avgs[i].set(round(((len(succ_list[i]))/trial)*100,1)) 
        pieces_left[i].set(str(round(mean(all_list[i]),2))) 
        most_likely[i].set(mode(all_list[i])) 
        root.update() 
       except: 
        None 
     attacker_total = attacker_total_original 
     first_round = True 
     for i in range(defender_total_spaces): 
      defender_total = defender_pieces_list[i] 
      while defender_total>0 and attacker_total > 0: 
       defender_win = False 
       attacker_win = False 

       defender_rolls_list = set_rolls(defender_total,2) 
       attacker_rolls_list = set_rolls(attacker_total,3) 
       if len(attacker_rolls_list) == 1: 
        defender_rolls_list = [randrange(1,7)] 

       for j in range(check_if_multiple(defender_rolls_list,attacker_rolls_list)): 
        if max(defender_rolls_list)>=max(attacker_rolls_list): 
         attacker_total += -1 
         defender_win = True 
        else: 
         defender_total += -1 
         attacker_win = True 
        attacker_rolls_list.remove(max(attacker_rolls_list)) 
        defender_rolls_list.remove(max(defender_rolls_list))  

       if first_round == True: 
        if defender_win == True and attacker_win == True: 
         first_round_split_total += 1 
        elif attacker_win == True: 
         first_round_attacker_total_wins += 1 
        elif defender_win == True: 
         first_round_defender_total_wins += 1 

       first_round = False 

      if defender_total == 0: 
       succ_list[i].append(attacker_total) 
       all_list[i].append(attacker_total) 
       if attacker_total == 1: 
        attacker_total == -1 

      if attacker_total == 0: 
       all_list[i].append(attacker_total) 

      attacker_total += -1 
    for i in range(0,defender_total_spaces): 
     try: 
      win_avgs[i].set(round(((len(succ_list[i]))/trial)*100,1)) 
      pieces_left[i].set(str(round(mean(all_list[i]),2))+"("+str(round(stdev(all_list[i]),1))+")") 
      most_likely[i].set(mode(all_list[i])) 
     except: 
      None 

height = 450 
width = 600 
shape = str(width) + "x" + str(height) 

root = Tk() 
root.title("Risk Probability Calculator") 
root.geometry(shape) 

content = ttk.Frame(root) 
content.grid(column=0, row=0, sticky=(N, W, E, S)) 
content.columnconfigure(0, weight=1) 
content.rowconfigure(0, weight=1) 

title = ttk.Label(content, text="Risk Probability Calculator", relief="ridge", background="gray",font=("TkHeadingFont",20),anchor="center") 
title.grid(column=1, row=1, columnspan=8, padx=3, pady=4,sticky=(N,W,E,S)) 

reset_button = ttk.Button(content, text="Reset", command=reset) 
reset_button.grid(column=1, row=2,padx=3, pady=4, sticky=(N, W, E, S)) 
go_button = ttk.Button(content, text="Go", command=go) 
go_button.grid(column=2, row=2,padx=3, pady=4, sticky=(N, W, E, S)) 

ttk.Label(content, text="Attacking with:").grid(column=1, row=3,padx=3, pady=4, sticky=(NW)) 
ttk.Label(content, text="Defending with:").grid(column=1, row=4,padx=3, pady=4, sticky=(NW)) 
for i in range(5,15): 
    text = "Space " + str(i-4) + ":" 
    ttk.Label(content, text=text).grid(column=1,padx=3, pady=4, row=i, sticky=(N,E,S)) 

attacker_amount = StringVar() 
attacker_entry = ttk.Entry(content, textvariable=attacker_amount, width=4) 
attacker_entry.grid(column=2, row=3,padx=3, pady=4, sticky=(N, W, S)) 

spaces = [] 
spaces_entry = [] 
for i in range(1, 11): 
    globals()['space'+str(i)] = StringVar() 
    spaces.append(globals()['space'+str(i)]) 

    globals()['space'+str(i)+'_entry'] = ttk.Entry(content, textvariable=spaces[i-1], width=4) 
    globals()['space'+str(i)+'_entry'].grid(column=2, row=(i+4),padx=3, pady=4, sticky=(N, W, S)) 
    spaces_entry.append(globals()['space'+str(i)+'_entry']) 

attacker_2 = Button(content, text="Attacker -2",command=lambda: subtract("att 2")) 
attacker_2.grid(column=4, row=2,padx=3, pady=4, sticky=(N,W,E,S)) 
attacker_1 = Button(content, text="Attacker -1",command=lambda: subtract("att 1")) 
attacker_1.grid(column=5, row=2,padx=3, pady=4, sticky=(N,W,E,S)) 
split_button = Button(content, text="Split",command=lambda: subtract("both")) 
split_button.grid(column=6, row=2,padx=3, pady=4, sticky=(N,W,E,S)) 
defender_1 = Button(content, text="Defender -1",command=lambda: subtract("def 1")) 
defender_1.grid(column=7, row=2,padx=3, pady=4, sticky=(N,W,E,S)) 
defender_2 = Button(content, text="Defender -2",command=lambda: subtract("def 2")) 
defender_2.grid(column=8, row=2,padx=3, pady=4, sticky=(N,W,E,S)) 

ttk.Separator(content,orient="vertical").grid(column=3,row=2,rowspan=15,padx=3, pady=4,sticky=(N,W,E,S)) 

results_frame = ttk.Labelframe(content, text='Results:') 
results_frame.grid(column=4, row=3, columnspan=5, rowspan=12,padx=3, pady=4, sticky=(N,W,E,S)) 

pane = ttk.Panedwindow(results_frame, orient='horizontal') 
pane.grid(column=1,row=1,columnspan=5,padx=3,sticky=(N,W,E,S)) 

pane1 = ttk.Labelframe(pane) 
pane.add(pane1) 
Label(pane1,text="% Win").grid(column=1,row=1,sticky=(N,W,E)) 

win_avgs = [] 
for i in range(1,11): 
    globals()['win_avg'+str(i)] = StringVar() 
    win_avgs.append(globals()['win_avg'+str(i)]) 
    Label(pane1,textvariable=win_avgs[i-1]).grid(column=1,row=i+1,padx=4, pady=4,sticky=(N,W,S)) 

pane2 = ttk.Labelframe(pane) 
pane.add(pane2) 
Label(pane2,text="Pieces Left").grid(column=1,row=1,sticky=(N,W,E)) 

pieces_left = [] 
for i in range(1,11): 
    globals()['pieces_left'+str(i)] = StringVar() 
    pieces_left.append(globals()['pieces_left'+str(i)]) 
    Label(pane2,textvariable=pieces_left[i-1]).grid(column=1,row=i+1,padx=4, pady=4,sticky=(N,W,S)) 

pane3 = ttk.Labelframe(pane) 
pane.add(pane3) 
Label(pane3,text="Most likely # of Pieces Left").grid(column=1,row=1,sticky=(N,W,E)) 

most_likely = [] 
for i in range(1,11): 
    globals()['most_likely'+str(i)] = StringVar() 
    most_likely.append(globals()['most_likely'+str(i)]) 
    Label(pane3,textvariable=most_likely[i-1]).grid(column=1,row=i+1,padx=4, pady=4,sticky=(N,W,S)) 

root.mainloop() 
+2

관련 코드를 게시 할 수 있습니까? – chris

답변

0

짧은 대답은 당신이 root.update()를 호출하기 때문에이 점이다. 이렇게하면 화면이 다시 그려 지지만 보류중인 모든 이벤트가 처리됩니다. 엄지 손가락의 좋은 규칙은 정확한 이유에 대해 "절대 update으로 전화하십시오."입니다. 드문 경우지만 단순히 코드를 구성하는 더 좋은 방법이 있습니다. 몇 밀리 초 밖에 걸리지 않는 함수에서 수행하는 경우 가끔 있습니다. 그러나 함수가 많은 것을 계산하는 것처럼 보입니다. 사용자가 키를 누르거나 버튼을 클릭 한 다음 update으로 전화하면, tkinter는 계속하기 전에 해당 이벤트를 처리하려고 시도합니다.

먼저 전화를 끊고 어떤 일이 발생하는지 먼저 확인하는 것이 좋습니다. 화면이 멈추는 경우 (실행하려고하는 코드의 양을 고려할 때) root.update_idletasks()으로 바꿀 수 있습니다. 그러면 클릭이나 버튼 이벤트가 처리되지 않고 '화면 다시 페인트'와 같은 특정 이벤트 클래스 만 처리됩니다.

관련 문제