Как сделать кнопку, которая на некоторое время останавливает мою нить

#python #tkinter

Вопрос:

Я пытаюсь сделать кнопку, которая останавливает мою нить, в которой есть время, но я не совсем уверен, как это сделать. Мне просто в основном нужно остановить оператор while, но я не уверен, является ли лучшим выбором найти способ остановить поток или попытаться сделать что-то, что остановит время в потоке, например, использовать горячую клавишу и заставить кнопку «Стоп» использовать pyautogui, чтобы нажать эту горячую клавишу. Я только начал всему этому учиться, так что, пожалуйста, потерпите меня. Также мы высоко ценим любые улучшения в моем коде! (Игнорируйте то, что говорит моя команда кнопки «Стоп». Я просто скопировал и вставил его туда, чтобы посмотреть, появится ли кнопка, что он и сделал)

 from tkinter import *
from poke import start
import pyautogui
import sys
import threading

myWindow = Tk()
myWindow.title("TFT Bot")
myWindow.configure(background="#EEEEEE")
Label(myWindow, text="TFT Bot", bg="#EEEEEE", fg="#555555", font="Times 20 bold underline").pack()
myWindow.geometry("600x400 200 250")

exitbutton = Button(myWindow, text="Exit", command=myWindow.destroy)
exitbutton.place(x=285,y=100)
      
startbutton = Button(myWindow, text="Start", command=lambda:threading.Thread(target=start).start())
startbutton.place(x=260,y=200)

stopbutton = Button(myWindow, text="Stop", command=lambda:threading.Thread(target=start).start())
stopbutton.place(x=360,y=400)

startbutton.pack()
stopbutton.pack()
exitbutton.pack()

myWindow.mainloop() 
 

Моя функция запуска:

 from pyautogui import *
import pyautogui
import time
import keyboard
import random
import win32api, win32con
import sys
def start():

    while keyboard.is_pressed('q') == False:
    #PLAY    
        play = pyautogui.locateCenterOnScreen('./images/play.png', confidence = 0.8)
        if play:
            print ("clicking play")
            pyautogui.moveTo(play)
            time.sleep(1)
            pyautogui.click(play, clicks=2, interval=1)
            time.sleep(0.05)
 

а затем это просто куча строк, которые похожи на первое утверждение if

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

1. вам нужно будет использовать command=lambda:threading.Thread(target=start).start() , чтобы передать функцию в качестве аргумента команды. В противном случае он выполнит строку до того, как вы нажмете кнопку (при запуске). Также вы не определили никакой функции запуска. Также нет необходимости говорить from pyautogui import * , и import pyautogui как вы будете импортировать его дважды, как это (просто используйте один из них, а не оба).

2. @sputnick567 на самом деле функция запуска определена в from poke import start , но я думаю, что OP также должен предоставить информацию об этой функции запуска.

3. @Xitiz да, спасибо, ты этого не видел.

4. @hwangsa теперь я в замешательстве, в чем для вас главная проблема? Потому что в вашем коде есть несколько проблем. Пожалуйста, расскажите точно, если возможно вкратце, в чем именно заключается ваша проблема?

5. @xitiz Я просто хочу знать, как я могу закодировать свою кнопку «стоп», чтобы остановить поток, который находится от моей кнопки «Пуск».

Ответ №1:

Просто чтобы остановить поток, вы можете попробовать это :

 import threading
import time

def run(stop):
    while True:
        print('thread running')
        if stop():
                break
                 
def main():
        stop_threads = False
        t1 = threading.Thread(target = run, args =(lambda : stop_threads, ))
        t1.start()
        time.sleep(1)
        stop_threads = True
        t1.join()
        print('thread killed')
main()
 

Это основной пример, но он очень важен для вашей проблемы. Для вас вы можете попробовать вот так :

 def start(stop):
    while True:
        play = pyautogui.locateCenterOnScreen('./images/play.png', confidence = 0.8)
        if play:
            print ("clicking play")
            pyautogui.moveTo(play)
            time.sleep(1)
            pyautogui.click(play, clicks=2, interval=1)
            time.sleep(0.05)     
            .......
     if stop() :
         break 

stop_threads=False

startbutton = Button(myWindow,text="Start",command=lambda : threading.Thread(target = start, args =(lambda : stop_threads, )).start())

startbutton.place(x=260,y=200)

def test():
    global stop_threads
    stop_threads=True

stopbutton = Button(myWindow, text="Stop", command=test)
stopbutton.place(x=360,y=400)
 

Я в основном создал поток, почти такой же, как у вас, но разница в том, что я использовал один параметр только для остановки этого потока.

Для получения дополнительной информации об этом вы можете посетить здесь, есть и другой способ остановить поток. Но я обнаружил, что это проще для вашего кода.

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

1. Это отлично сработало для меня! Протестируйте его и сообщите мне, работает он или нет?

2. @xitix Кнопка «стоп» работает, но она работает только тогда, когда я переключаю вкладку клиента, на котором пытаюсь использовать бота. Есть ли способ остановить его между щелчками в моей функции «Пуск»?

3. Что вы имеете в виду под » Я могу остановить его в промежутках между щелчками с помощью функции»Пуск»» ? Вы пытаетесь остановить поток через какой-то x секунд?

4. Я просто хочу остановить поток, когда нажимаю кнопку «Стоп», но он останавливается только тогда, когда я нажимаю alt tab на клиенте, на который нажимает код. Поэтому, когда pyautogui что-то находит, кнопка «Стоп» не останавливает поток.

5. Я хотел сказать, что если бы pyautogui ничего не мог найти, кнопка «Стоп» работала бы только тогда. Но я нашел способ заставить это работать сейчас, поэтому я думаю, что на мой вопрос был дан ответ, так как теперь он хорошо работает с помощью совета, который вы мне дали. Спасибо вам за помощь! @xitiz