鼠标或者键盘触发的tkinter如何多线程

原始代码通用性不高,且自用代码,仅供参考。
内容大概是这样的。
1、tkinter界面长显示,有三个Text显示栏,其中的显示内容text根据信号触发后显示,简化而言可以是认为是任意不同数据。
2.触发信号可以是鼠标双击,也可以是键盘的某个按钮比如F2等,代码里是双击。
在单线程的情况下,信号触发后,内容text可以根据信息更新,但是界面却不能拖动等,不然必死机。请看看如何做到多线程,并作一个简单的示例,或者直接修改代码。

import pyautogui as gui
import win32api
import time
import pyperclip as pc
import pandas as pd
import tkinter as tk
from tkinter.font import Font
"""此处为将excel转换为dataframe格式,以型号为准,去重,以日排程号作为index,不然后续曲轴箱曲轴的格式不为str"""
df=pd.read_excel('Book1.xlsx',sheet_name='曲轴箱',dtype=str)
df.drop_duplicates(subset='型号',keep='first',inplace=True)
df.set_index(['日排程号'],inplace=True)
global txt,xiang,zhou
"""此处为tkinter设置,结合下面的自动更新"""
windows=tk.Tk()
windows.geometry('300x200+840+320')
windows.resizable(False,False)
lbl1=tk.Label(windows,text='  型号:',font=12)
lbl2=tk.Label(windows,text='曲轴箱:',font=12)
lbl1.grid(row=0,column=0)
lbl2.grid(row=1,column=0)
lbl3=tk.Label(windows,text='  曲轴:',font=12)
lbl3.grid(row=2,column=0)
text1=tk.Text(windows,width=40,height=1)
text2=tk.Text(windows,width=40,height=1)
text3=tk.Text(windows,width=40,height=1)
text1.grid(row=0,column=1,padx=5,pady=10)
text2.grid(row=1,column=1,padx=5,pady=10)
text3.grid(row=2,column=1,padx=5,pady=10)
myFont =Font(size=12)
text1.configure(font=myFont)
text2.configure(font=myFont)
text3.configure(font=myFont)
windows.wm_attributes('-topmost',1)#置顶

"""判定快速双击"""
state_left = win32api.GetKeyState(0x01)  # Left button release = 0 or 1. Button press = -127 or -128
while True:
    a= win32api.GetKeyState(0x01)
    key=False
    if a!=state_left:
        state_left=a
        try:
            if a in [-127,-128]:
                t1=time.time()
            if a in [0,1]:
                time.sleep(0.1)
                b = win32api.GetKeyState(0x01)
                if b in [-127,-128]:
                    t2=time.time()
                    if t2-t1<0.8:
                        key=True
        except:continue
    if key:
        gui.tripleClick()
        time.sleep(0.2)
        gui.hotkey('ctrl','c')
        time.sleep(0.2)
        txt=pc.paste()
        txt=txt.strip()
        try:
            row=df[df['型号']==txt]
            xiang=row['曲轴箱'][0]
            zhou=row['曲轴'][0]
            text1.delete(0.0, tk.END)
            text1.insert(tk.INSERT, txt)
            text2.delete(0.0, tk.END)
            text2.insert(tk.INSERT, xiang)
            text3.delete(0.0, tk.END)
            text3.insert(tk.INSERT, zhou)
            text1.update()
            text2.update()
            text3.update()
        except:pass
windows.mainloop()

问题就出在这个while True:上 它是死循环,双击一次,动一次,在双击之前,它不能动的,所以是【无响应】
等我改一下代码给你试试

步骤

  1. 把循环封装到回调函数里
  2. 启动新线程监听信号,执行回调,注意daemon=True

代码示例

iimport threading
import time
import tkinter as tk
from tkinter.font import Font

import pandas as pd
import pyautogui as gui
import pyperclip as pc
import win32api

"""此处为将excel转换为dataframe格式,以型号为准,去重,以日排程号作为index,不然后续曲轴箱曲轴的格式不为str"""
df = pd.read_excel("Book1.xlsx", sheet_name="曲轴箱", dtype=str)
df.drop_duplicates(subset="型号", keep="first", inplace=True)
df.set_index(["日排程号"], inplace=True)
global txt, xiang, zhou
"""此处为tkinter设置,结合下面的自动更新"""
windows = tk.Tk()
windows.geometry("300x200+840+320")
windows.resizable(False, False)
lbl1 = tk.Label(windows, text="  型号:", font=12)
lbl2 = tk.Label(windows, text="曲轴箱:", font=12)
lbl1.grid(row=0, column=0)
lbl2.grid(row=1, column=0)
lbl3 = tk.Label(windows, text="  曲轴:", font=12)
lbl3.grid(row=2, column=0)
text1 = tk.Text(windows, width=40, height=1)
text2 = tk.Text(windows, width=40, height=1)
text3 = tk.Text(windows, width=40, height=1)
text1.grid(row=0, column=1, padx=5, pady=10)
text2.grid(row=1, column=1, padx=5, pady=10)
text3.grid(row=2, column=1, padx=5, pady=10)
myFont = Font(size=12)
text1.configure(font=myFont)
text2.configure(font=myFont)
text3.configure(font=myFont)
windows.wm_attributes("-topmost", 1)  # 置顶

"""判定快速双击"""


def callback():
    state_left = win32api.GetKeyState(
        0x01
    )  # Left button release = 0 or 1. Button press = -127 or -128
    while True:
        a = win32api.GetKeyState(0x01)
        key = False
        if a != state_left:
            state_left = a
            try:
                if a in [-127, -128]:
                    t1 = time.time()
                if a in [0, 1]:
                    time.sleep(0.1)
                    b = win32api.GetKeyState(0x01)
                    if b in [-127, -128]:
                        t2 = time.time()
                        if t2 - t1 < 0.8:
                            key = True
            except:
                continue
        if key:
            gui.tripleClick()
            time.sleep(0.2)
            gui.hotkey("ctrl", "c")
            time.sleep(0.2)
            txt = pc.paste()
            txt = txt.strip()
            try:
                row = df[df["型号"] == txt]
                xiang = row["曲轴箱"][0]
                zhou = row["曲轴"][0]

                text1.delete(0.0, tk.END)
                text1.insert(tk.INSERT, txt)
                text2.delete(0.0, tk.END)
                text2.insert(tk.INSERT, xiang)
                text3.delete(0.0, tk.END)
                text3.insert(tk.INSERT, zhou)
                text1.update()
                text2.update()
                text3.update()
            except:
                pass


t = threading.Thread(target=callback, daemon=True)
t.start()

windows.mainloop()

我这边有个简单的例子,你可以参考一下


# coding:utf-8
from tkinter import *
from tkinter import scrolledtext
import threading
import time
from PIL import ImageTk, Image


def count(i):
    for k in range(1, 100):
        text.insert(END, '第' + str(i) + '线程count:  ' + str(k) + '\n')
        time.sleep(0.001)


def fun():
    for i in range(1, 5):
        th = threading.Thread(target=count, args=(i,))
        th.setDaemon(True)  # 守护线程
        th.start()
    var.set('MDZZ')


root = Tk()
root.title('夜雨飞花')  # 窗口标题
root.geometry('+600+100')  # 窗口呈现位置
image2 = Image.open(r'ParticleSmoke.png')
background_image = ImageTk.PhotoImage(image2)
textlabel = Label(root, image=background_image)
textlabel.grid()
text = scrolledtext.ScrolledText(root, font=('微软雅黑', 10), fg='blue')
text.grid()
button = Button(root, text='荣耀王者,等你来挑战', font=('微软雅黑', 10), command=fun)
button.grid()
var = StringVar()  # 设置变量
label = Label(root, font=('微软雅黑', 10), fg='red', textvariable=var)
label.grid()
var.set('努力上分')
root.mainloop()


coding:utf-8

from tkinter import *
from tkinter import scrolledtext
import threading
import time
from PIL import ImageTk, Image

def count(i):
for k in range(1, 100):
text.insert(END, '第' + str(i) + '线程count: ' + str(k) + '\n')
time.sleep(0.001)

def fun():
for i in range(1, 5):
th = threading.Thread(target=count, args=(i,))
th.setDaemon(True) # 守护线程
th.start()
var.set('MDZZ')

root = Tk()
root.title('夜雨飞花') # 窗口标题
root.geometry('+600+100') # 窗口呈现位置
image2 = Image.open(r'ParticleSmoke.png')
background_image = ImageTk.PhotoImage(image2)
textlabel = Label(root, image=background_image)
textlabel.grid()
text = scrolledtext.ScrolledText(root, font=('微软雅黑', 10), fg='blue')
text.grid()
button = Button(root, text='荣耀王者,等你来挑战', font=('微软雅黑', 10), command=fun)
button.grid()
var = StringVar() # 设置变量
label = Label(root, font=('微软雅黑', 10), fg='red', textvariable=var)
label.grid()
var.set('努力上分')
root.mainloop()