2016-01-21 2 views
1

В настоящее время я создаю программу, которая будет постоянно проверять нажатие клавиши, и если это W или S, это изменит скорость. Но у меня проблема с ТК, не отвечающая? Кто-нибудь помогает ура. Мой код:Python - While Loop меняет переменную

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 при каждом нажатии клавиши.

Пара ключевых вещей, которые вам нужно знать о tkinter, заключается в том, что time.sleep следует избегать и пытаться иметь, когда петли работают в фоновом режиме.

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

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

Side Примечание:

В настоящее время, когда я нажимаю письмо будет вставить "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», у вас будет один вызов функции на клавишу.

Допустим, вы нажимаете «ш», то:
- функция называется: установить скорость = 50
- вы входите в то время цикла, (скорость> 0)
- проверьте нажатой клавиши.
- так как это 'w', скорость = 51
- начиная с скорости> 0, повторите цикл.
-----> Это будет «никогда», поскольку скорость никогда не < 0 и значение скорости не печатается.

Допустим, вы нажимаете 's', то:
- функция называется: установить скорость = 50
- вы входите в то время цикла, (скорость> 0)
- проверьте нажатой клавиши.
- Так как это 's', скорость = 49
- значение скорости печати
- так как скорость> 0, повторите цикл. -----> Это в конечном итоге закончится.

Допустим, вы нажимаете некоторую другую клавишу, а затем:
- функция называется: установить скорость = 50
- вы входите в то время цикла, (скорость> 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

любое решение, которое вызывает 'sleep' в приложении tkinter, в корне ошибочно. Пока приложение спал, tkinter не может обрабатывать какие-либо события (включая обновление экрана). –

+0

@BryanOakley, я полностью согласен. Я просто оставил его, потому что пользователь сказал, что приложение врезалось в противном случае. – tglaria

0

вы никогда не можете сделать две вещи, как графический интерфейс и перекручивание то же время в главном потоке или на главном process.you используют в то время как цикл .so, что происходит, когда программа ввода в то время как цикл он работает непрерывно, не давая каких-либо ресурсов к gui.
, поэтому для выполнения этой работы используйте модуль поточной передачи и очередь.