如何阻止 Tkinter 从 while 循环中冻结?
How to stop Tkinter from freezing from while loop?
我正在尝试为我的代码创建一个 GUI。每次将新内容复制到剪贴板时,它都会在 ebay 上搜索那些已售出的商品。我希望我的代码在每次复制某些内容时始终 运行 ebay 函数。我遇到的问题是我想有一个关闭按钮来终止该功能,这样我就可以保持 GUI 打开并根据需要打开和关闭它。我尝试了线程、root.after 和其他一些方法来尝试修复我的代码,但每次按下打开按钮时,我的 GUI 仍然冻结。我做错了什么/如何让 GUI 在始终从剪贴板中搜索新值的同时保持运行?
import threading
import sys
import os
import webbrowser
sys.path.append(os.path.abspath("SO_site-packages"))
import pyperclip
import tkinter as tk
run = True
def ebay():
current=""
while run == True:
new = pyperclip.paste()
if new != current:
current = new
webbrowser.open('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
thread = threading.Thread()
thread.start()
def switchon():
global run
run = True
ebay()
def switchoff():
global run
run = False
def main():
root = tk.Tk()
root.title("EbayPaste")
root.geometry('400x300')
onbutton = tk.Button(root, text="ON", command=switchon)
onbutton.pack()
offbutton = tk.Button(root, text="OFF", command=switchoff)
offbutton.pack()
root.mainloop()
thread2 =threading.Thread
thread2.start(main())
if __name__ == '__main__':
main()
您对 threading.Thread()
的使用不太正确,因为它没有有效的目标。另外,我不确定你为什么要 start/stop 这个程序,所以在我的解决方案中我已经去掉了那个功能(尽管如果你 真的 想要你可以找出一个获得方式)。大大简化的代码可以完成我 认为 你想要完成的事情(在 ebay 上搜索剪贴板中的所有内容):
import threading
import sys
import os
import webbrowser
sys.path.append(os.path.abspath("SO_site-packages"))
import pyperclip
import tkinter as tk
def ebay():
current = ""
new = pyperclip.paste()
if new != current:
current = new
webbrowser.open('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
def open_ebay():
thread = threading.Thread(target=ebay)
thread.start()
thread.join()
def main():
root = tk.Tk()
root.title("EbayPaste")
root.geometry('400x300')
tk.Button(root, text="load ebay from clipboard", command=open_ebay).pack()
root.mainloop()
if __name__ == '__main__':
main()
@EDIT
好的,我想这会得到您想要的。您将需要安装 selenium,为此我将向您推荐 https://selenium-python.readthedocs.io/installation.html
import threading
import pyperclip
import tkinter as tk
import time
from selenium import webdriver
class myGUI:
def __init__(self):
self.thread_running = bool
self.win = tk.Tk()
self.win.title("EbayPaste")
self.win.geometry('400x300')
tk.Button(self.win, text="load ebay from clipboard", command=self.start_thread).pack()
tk.Button(self.win, text="Stop thread", command=self.close_thread).pack()
def close_thread(self):
self.thread_running = False
def start_thread(self):
self.thread_running = True
thread = threading.Thread(target=self.ebay)
thread.start()
def ebay(self):
self.driver = webdriver.Chrome()
old = ""
loop = 0
while self.thread_running:
print('running loop {}'.format(loop))
loop += 1
time.sleep(1)
new = pyperclip.paste()
if new != old:
old = new
self.driver.get('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
self.driver.quit()
if __name__ == '__main__':
app = myGUI()
app.win.mainloop()
这将生成一个线程,每 1 秒检查一次剪贴板是否有更改。如果有变化,它将在它产生的浏览器中将其拉出。当用户关闭线程时,浏览器将自动关闭。通过这种方法,GUI 不会冻结!如果这有助于解决您的问题,那么如果您可以单击 post 旁边的复选标记以接受答案,那就太好了。如果你真的喜欢它,你也可以给它+投票:D
我正在尝试为我的代码创建一个 GUI。每次将新内容复制到剪贴板时,它都会在 ebay 上搜索那些已售出的商品。我希望我的代码在每次复制某些内容时始终 运行 ebay 函数。我遇到的问题是我想有一个关闭按钮来终止该功能,这样我就可以保持 GUI 打开并根据需要打开和关闭它。我尝试了线程、root.after 和其他一些方法来尝试修复我的代码,但每次按下打开按钮时,我的 GUI 仍然冻结。我做错了什么/如何让 GUI 在始终从剪贴板中搜索新值的同时保持运行?
import threading
import sys
import os
import webbrowser
sys.path.append(os.path.abspath("SO_site-packages"))
import pyperclip
import tkinter as tk
run = True
def ebay():
current=""
while run == True:
new = pyperclip.paste()
if new != current:
current = new
webbrowser.open('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
thread = threading.Thread()
thread.start()
def switchon():
global run
run = True
ebay()
def switchoff():
global run
run = False
def main():
root = tk.Tk()
root.title("EbayPaste")
root.geometry('400x300')
onbutton = tk.Button(root, text="ON", command=switchon)
onbutton.pack()
offbutton = tk.Button(root, text="OFF", command=switchoff)
offbutton.pack()
root.mainloop()
thread2 =threading.Thread
thread2.start(main())
if __name__ == '__main__':
main()
您对 threading.Thread()
的使用不太正确,因为它没有有效的目标。另外,我不确定你为什么要 start/stop 这个程序,所以在我的解决方案中我已经去掉了那个功能(尽管如果你 真的 想要你可以找出一个获得方式)。大大简化的代码可以完成我 认为 你想要完成的事情(在 ebay 上搜索剪贴板中的所有内容):
import threading
import sys
import os
import webbrowser
sys.path.append(os.path.abspath("SO_site-packages"))
import pyperclip
import tkinter as tk
def ebay():
current = ""
new = pyperclip.paste()
if new != current:
current = new
webbrowser.open('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
def open_ebay():
thread = threading.Thread(target=ebay)
thread.start()
thread.join()
def main():
root = tk.Tk()
root.title("EbayPaste")
root.geometry('400x300')
tk.Button(root, text="load ebay from clipboard", command=open_ebay).pack()
root.mainloop()
if __name__ == '__main__':
main()
@EDIT
好的,我想这会得到您想要的。您将需要安装 selenium,为此我将向您推荐 https://selenium-python.readthedocs.io/installation.html
import threading
import pyperclip
import tkinter as tk
import time
from selenium import webdriver
class myGUI:
def __init__(self):
self.thread_running = bool
self.win = tk.Tk()
self.win.title("EbayPaste")
self.win.geometry('400x300')
tk.Button(self.win, text="load ebay from clipboard", command=self.start_thread).pack()
tk.Button(self.win, text="Stop thread", command=self.close_thread).pack()
def close_thread(self):
self.thread_running = False
def start_thread(self):
self.thread_running = True
thread = threading.Thread(target=self.ebay)
thread.start()
def ebay(self):
self.driver = webdriver.Chrome()
old = ""
loop = 0
while self.thread_running:
print('running loop {}'.format(loop))
loop += 1
time.sleep(1)
new = pyperclip.paste()
if new != old:
old = new
self.driver.get('https://www.ebay.ca/sch/i.html?_from=R40&_nkw=' + str(new) + '&LH_Sold=1&LH_Complete=1&LH_ItemCondition=3000')
self.driver.quit()
if __name__ == '__main__':
app = myGUI()
app.win.mainloop()
这将生成一个线程,每 1 秒检查一次剪贴板是否有更改。如果有变化,它将在它产生的浏览器中将其拉出。当用户关闭线程时,浏览器将自动关闭。通过这种方法,GUI 不会冻结!如果这有助于解决您的问题,那么如果您可以单击 post 旁边的复选标记以接受答案,那就太好了。如果你真的喜欢它,你也可以给它+投票:D