2016-01-21 222 views
1

我目前正在創建一個程序,將不斷檢查按鍵,如果它是W或S它會改變速度。但是我有一個Tk沒有迴應的問題?任何人都會幫助歡呼。我的代碼是:Python - while循環更改變量

import tkinter as tk #Importing the GUI Library 
import time #Importing Time# 
def onKeyPress(event): #Defining my function of keypress, and using GUI Library to get the keypress. 
     time.sleep(1) #Telling it to wait one second otherwise it will crash. 
     text.insert('end', 'You pressed %s\n' % (event.char,)) #Telling the user if he pressed the key or not. 
     speed = 50 #Setting the speed to 50 default 
     while speed > 0: 
      if event.char == 'w': #if key pressed = w: 
       speed = speed + 1 #Change speed by 1 
       time.sleep(1) 
      if event.char == 's': 
       speed = speed - 1 
       time.sleep(1) 
       print(speed) 


root = tk.Tk() 
root.geometry('300x200') 
text = tk.Text(root, background='black', foreground='white', font=('Comic Sans MS', 12)) 
text.pack() 
root.bind('<KeyPress>', onKeyPress) 
root.mainloop() 

回答

2

您的主要問題是,當您按下「s」以外的字母時,您將進入無限循環。當按's'時,只需要50秒退出循環,以便在下一次按鍵時再次開始。此外,您的速度變量僅在按鍵功能中,因此您無法訪問它,您每次按下某個按鍵時也將其重置爲50。應該大量避免,並試圖讓while循環在後臺運行。

現在有幾個選項可以做到這一點。您可以將該功能綁定到每個單獨的密鑰。

import tkinter as tk 

def onKeyPress(event, value): 
    global speed # alter the global speed variable inside a function 

    # Keep in mind this insert will only occur for the selected keys 
    text.insert('end', 'You pressed %s\n' % (event.char,)) 
    speed += value # update speed variable with value 
    print(speed) # print current speed 

speed = 50 

root = tk.Tk() 
root.geometry('300x200') 
text = tk.Text(root, background='black', foreground='white', font=('Comic Sans MS', 12)) 
text.pack() 

# Individual key bindings 
root.bind('<KeyPress-w>', lambda e: onKeyPress(e, 1)) # value is 1 for 'w' 
root.bind('<KeyPress-s>', lambda e: onKeyPress(e, -1)) # value is -1 for 's' 

root.mainloop() 

或者可以像以前一樣使用if語句來檢查輸入的字母。每個字母使用if elif而不是if,因爲儘管它具有相同的效果,但if條件將在條件爲True時終止,否則它將遍歷所有if語句。

import tkinter as tk 

def onKeyPress(event): 
    global speed # alter the global speed variable inside a function 

    text.insert('end', 'You pressed %s\n' % (event.char,)) 

    if event.char == 'w': 
     speed += 1 
    elif event.char == 's': 
     speed -= 1 
    print(speed) # print current speed 

speed = 50 

root = tk.Tk() 
root.geometry('300x200') 
text = tk.Text(root, background='black', foreground='white', font=('Comic Sans MS', 12)) 
text.pack() 
root.bind('<KeyPress>', onKeyPress) 

root.mainloop() 

側面說明:

目前,當我按下一個字母,它將插入"sYou pressed s",因爲最初的按鍵的。如果你在插入行之前添加它,那麼它將刪除給出"You pressed s"的輸入字符。

text.delete("%s-1c" % 'insert', 'insert') 
+0

謝謝!正是我想要的。 –

1

Tk沒有響應,因爲事件處理程序中的while循環永遠不會完成。 看來你甚至不需要它在那個地方,所以不是

def onKeyPress(event): 
    while True: 
     time.sleep(1) 
     text.insert('end', 'You pressed %s\n' % (event.char,)) 
    .... 

簡單

def onKeyPress(event): 
    text.insert('end', 'You pressed %s\n' % (event.char,)) 
    ... 

應該做的工作。

主循環不在單個事件處理程序中,而是在外部並且已由最後一行啓動。

-1

我沒有看到你說你想要什麼,你在你的代碼之間有什麼關係:

def onKeyPress(event): 
    time.sleep(1) #Telling it to wait one second otherwise it will crash. 
    text.insert('end', 'You pressed %s\n' % (event.char,)) 
    speed = 50  # This is set on each keypress? 
    while speed > 0:   # why? 
     if event.char == 'w': 
      speed = speed + 1 
      time.sleep(1) 
     if event.char == 's': 
      speed = speed - 1 
      time.sleep(1) 
      print(speed)  # inside the second if? Why? 

首先,你每段時間設定在50的速度,你按一個鍵(任何鍵)。

其次,爲什麼你的'按鍵'功能中有一個循環?
每次按(任意)鍵時都會調用此函數,所以如果按'w',然後's'或者甚至't',則每個鍵都會有一個函數調用。

比方說,你按 'W',則:
- 函數被調用:您設定的速度= 50
- 您進入一個while循環,(速度> 0)
- 檢查按鍵。
- 由於它是'w',速度= 51
- 由於速度> 0,因此重做循環。
----->這將「永不」結束,因爲速度永不是< 0,並且不打印速度值。

比方說,你按 'S',則:
- 函數被調用:您設定的速度= 50
- 您進入一個while循環,(速度> 0)
- 檢查按鍵。
- 既然是'',速度= 49
- 打印速度值
- 由於速度> 0,因此重做循環。 ----->這最終會結束。

比方說,你按一些其他的鍵,然後:
- 函數被調用:您設定的速度= 50
- 您進入一個while循環,(速度> 0)
- 檢查按鍵。
- 因爲它是另一個關鍵,速度= 50,沒有改變 - 因爲速度> 0,重做循環....永遠...... ---->在這種情況下,你會有一個永無止境的循環沒有印刷任何東西。


你想要什麼(我想)? 這對我有用。

speed = 50 #Leave it out of the function. 
def onKeyPress(event): 
    #time.sleep(1) # You shouldn't have a sleep() inside a function called by tkinter. 
    text.insert('end', 'You pressed %s\n' % (event.char,)) 
    global speed  #So you can alter its value 
    #No loop inside function 
    if event.char == 'w': 
     speed = speed + 1 
    if event.char == 's': 
     speed = speed - 1 
    print(speed)  # Outside of function, so you can see the present value. 
+0

在tkinter應用程序中調用'sleep'的任何解決方案都有根本的缺陷。當應用程序正在休眠時,tkinter無法處理任何事件(包括刷新屏幕)。 –

+0

@BryanOakley,我完全同意。我剛剛離開它,因爲用戶說應用程序崩潰,否則。 – tglaria

0

你永遠無法做到像GUI和循環在主線程或主process.you同時兩件事情是使用while循環。所以當程序進入while循環,它不斷地而不給予任何資源運行會發生什麼去gui。
所以利用線程模塊和隊列來完成這項工作。