Используя графический интерфейс tkinter, я хочу запустить программу без ее зависания, чтобы пользователь мог взаимодействовать с программой во время ее выполнения

#python #tkinter

#питон #tkinter

Вопрос:

Я приношу извинения за длинный код и запутанные вводные данные, мне пришлось кое-что сделать в ретроспективе. Эта программа считает (вводит число) до определенного числа (ограничено 100, потому что я обленился) и предназначена для игры (отсюда / и пробел, ввод входных данных). Все работает хорошо, вы можете попробовать это в блокноте.

Однако при запуске программы все зависает до тех пор, пока подсчет не будет завершен. Я слышал о потоковой передаче, хотя, к сожалению, не могу этого понять. Чего я хочу добиться, так это того, чтобы программа могла запускаться, и пользователь все еще мог взаимодействовать с ней во время ее запуска и приостанавливать / останавливать программу, если он того пожелает. Я настроил наивную кнопку ОСТАНОВКИ, но она не работает при ее запуске, а также закрывает программу, которая неидеальна, так как я бы предпочел просто приостановить или отменить подсчет.

 from pynput import keyboard as keyboard3
import time
import keyboard as keyboard2
import tkinter as tk
from functools import partial
import sys


num2words = {1: 'One', 2: 'Two', 3: 'Three', 4: 'Four', 5: 'Five',
            6: 'Six', 7: 'Seven', 8: 'Eight', 9: 'Nine', 10: 'Ten',
            11: 'Eleven', 12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen',
            15: 'Fifteen', 16: 'Sixteen', 17: 'Seventeen', 18: 'Eighteen', 19: 'Nineteen'}
num2wordsTens = ['Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety']

def exitProgram():
    sys.exit()

def num2text(numb,caps):
    """
    :param numb: number to convert to text
    :param caps: True/False capital returns
    :return: Take the integer and returns text equivalance
    """
    if 0 <= numb <= 19:
        if caps:
            return (num2words[numb]).upper()
        else:
            return (num2words[numb])
    elif 20 <= numb <= 99:
        tens, remainder = divmod(numb, 10)
        if caps:
            return (num2wordsTens[tens - 2]   ' '   num2words[remainder] if remainder else num2wordsTens[tens - 2]).upper()
            #Can add "  '-'  " if we want a hyphonate it.
        else:
            return num2wordsTens[tens - 2]   ' '   num2words[remainder] if remainder else num2wordsTens[tens - 2]
    elif numb == 100:
        return "One Hundred"
    else:
        print('Number out of implemented range of numbers.')


keyboard = keyboard3.Controller()


def jumpingJacks(maxNumb, initDelay, intervalDelay, caps, grammar):
    """
    :param maxNumb: Max number for the list of numbers
    :param initDelay: Initial delay before starting
    :param intervalDelay: Delay between sending messages
    :param grammar: If true, add fullstop.
    :return: none
    """
    time.sleep(initDelay.get())
    numberInterval = list(range(1, maxNumb.get() 1))
    for integer in numberInterval:
        keyboard.tap('/')
        time.sleep(0.1)
        if grammar:
            keyboard.type(num2text(numberInterval[integer-1], caps) '.')
        else:
            keyboard.type(num2text(numberInterval[integer-1], caps))
        time.sleep(0.1)
        keyboard2.press('enter')
        time.sleep(0.1)
        keyboard2.press('space')
        time.sleep(0.5)
        keyboard2.release('space')
        time.sleep(intervalDelay.get())

window = tk.Tk()
window.geometry("500x200")

numJJ = tk.IntVar(value=10)
intDelay = tk.IntVar(value=5)
JJDelay = tk.IntVar(value=1.5)
capsCheck = tk.BooleanVar()
grammarCheck = tk.BooleanVar()

frame_top = tk.Frame(master=window)
frame_1 = tk.Frame(master=frame_top)
labelt1 = tk.Label(master=frame_1, text="Number of JJ")
entryt1 = tk.Entry(master=frame_1, width=5, textvariable=numJJ)
labelt1.pack(side=tk.TOP, padx=10,pady=(5,1))
entryt1.pack(side=tk.TOP)

frame_2 = tk.Frame(master=frame_top)
labelt2 = tk.Label(master=frame_2, text="Initial Delay (s)")
entryt2 = tk.Entry(master=frame_2, width=3, textvariable=intDelay)
labelt2.pack(side=tk.TOP,padx=10, pady=(5,1))
entryt2.pack()

frame_3 = tk.Frame(master=frame_top)
labelt3 = tk.Label(master=frame_3, text="JJ Delay (s)")
entryt3 = tk.Entry(master=frame_3, width=3, textvariable=JJDelay)
labelt3.pack(side=tk.TOP,padx=10, pady=(5,1))
entryt3.pack()


frame_4 = tk.Frame(master=frame_top)
labelt4 = tk.Label(master=frame_4, text="Capslock?")
checkt4 = tk.Checkbutton(master=frame_4, onvalue=True, offvalue=False, variable=capsCheck)
labelt4.pack(side=tk.TOP,padx=10,pady=(5,1))
checkt4.pack()

frame_5 = tk.Frame(master=frame_top)
labelt5 = tk.Label(master=frame_5, text="Grammar?")
checkt5 = tk.Checkbutton(master=frame_5, onvalue=True, offvalue=False, variable=grammarCheck)
labelt5.pack(side=tk.TOP,padx=10, pady=(5,1))
checkt5.pack()

frame_bottom = tk.Frame(master=window)

jumpingJacks = partial(jumpingJacks, numJJ, intDelay, JJDelay, capsCheck, grammarCheck)
toggleButton = tk.Button(master=frame_bottom, text="Begin", command=jumpingJacks)
toggleButton.pack()

ExitButton = tk.Button(master=frame_bottom,text="Stop",command=exitProgram)
ExitButton.pack()

frame_1.pack(side=tk.LEFT)
frame_2.pack(side=tk.LEFT)
frame_3.pack(side=tk.LEFT)
frame_4.pack(side=tk.LEFT)
frame_5.pack(side=tk.LEFT)

frame_top.pack()
frame_bottom.pack()
window.mainloop()
 

Комментарии:

1. почему вы использовали список num2words. в python есть модуль под названием num2words, который преобразует числовую строку в словесную строку. ваш код может стать короче при использовании этого

2. threading это идеальное решение для вас (и, возможно, единственное). FWIW, threading на самом деле проще, чем кажется тому, кто им не пользуется. Как только вы овладеете ею, возврата не будет 😉 Посмотрите несколько руководств по потокам, обратитесь к документации, НЕ пытайтесь сразу реализовать свои варианты использования. Сначала поэкспериментируйте с потоками. Создавайте программы для развлечения. и после этого вы сможете легко реализовать свой вариант использования. Удачи.

3. @PSSolanki прав. Вы должны реализовать потоковую обработку в своем коде