如何从While循环中阻止Tkinter冻结?

问题描述

我正在尝试为我的代码创建一个图形用户界面。每当有新的东西被复制到剪贴板上,它就会在eBay上搜索那些已售出的物品。我希望我的代码总是在每次复制东西时运行eBay函数。我的问题是,我想有一个关闭按钮,取消该功能,这样我就可以保持图形用户界面打开和切换它,因为我喜欢。我已经尝试了线程、root.After和其他几种方法来尝试修复代码,但每次按下On按钮时,我的图形用户界面仍然冻结。我做错了什么/如何在始终从剪贴板中搜索新值的同时使图形用户界面保持正常工作?

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()的使用不完全正确,因为它没有有效的目标。此外,我不确定您为什么要启动/停止该程序,因此在我的解决方案中,我已经去掉了该功能(尽管如果您真的想要的话,您可以想出一种方法来获得它)。大大简化的代码实现了我认为您正在尝试实现的目标(在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()

@编辑

好的,我想这会得到你想要的东西。您需要安装Selify,我将向您推荐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秒检查一次剪贴板的更改。如果有变化,它会在它产生的浏览器中将其拉出。当用户关闭线程时,浏览器将自动关闭。通过这种方法,图形用户界面不会冻结!如果这有助于解决你的问题,如果你能点击帖子旁边的复选标记来接受答案,那就太好了。如果你真的喜欢它,你也可以给它加一票:d

相关文章