Python Tkinter:循环运行时窗口冻结

Python Tkinter:循环运行时窗口冻结,python,multithreading,tkinter,Python,Multithreading,Tkinter,我什么都试过了,但我一点也不懂如何应用线程。拜托,有人能告诉我怎么做才对吗?我试过几个例子,结果总是一样的。直到“ping”循环完成,“stop”按钮才停止。请,我是一个新手,给我一个简单的解释如何应用线程 from tkinter import * from tkinter import ttk from tkinter import scrolledtext import pandas as pd from pythonping import ping from datetime impor

我什么都试过了,但我一点也不懂如何应用线程。拜托,有人能告诉我怎么做才对吗?我试过几个例子,结果总是一样的。直到“ping”循环完成,“stop”按钮才停止。请,我是一个新手,给我一个简单的解释如何应用线程

from tkinter import *
from tkinter import ttk
from tkinter import scrolledtext
import pandas as pd
from pythonping import ping
from datetime import datetime
import numpy as np

running = False  # Global flag

def start_ping():
    
    if running:  # Only do this if the Stop button has not been clicked
        
        indices_tabla = tabla.get_children()
        
        for x_fila in range(0,df_registro.shape[0]):
            
            celda_nombres =  list(df_registro["NOMBRE"])[x_fila]
            celda_ip = list(df_registro["IP"])[x_fila]

            ping_equipo = ping(str(celda_ip), count=1)
                           
            msg = (celda_nombres + ' (' + celda_ip + ')\n' +
                   '\n' +
                   str(datetime.now()) + '\n' +
                   '\n' +
                   str(ping_equipo) + '\n' +
                   '\n' +
                   '--------------------------------------------------' + '\n' + '\n')
            
            text_box.insert(END, msg)

            text_box.yview(END)
            text_box.update()
            
            if ping_equipo.success():
                
                
                df_registro.at[x_fila,'P. Enviados'] = int(df_registro.at[x_fila,'P. Enviados']) + 1
                
                celda_p_enviados = df_registro.at[x_fila,'P. Enviados']
                celda_p_perdidos = df_registro.at[x_fila,'P. Perdidos']
                
                tabla.delete(indices_tabla[x_fila])
                
                tabla.insert("", index=x_fila, text=str(celda_nombres), iid=str(indices_tabla[x_fila]),
                                 values=(str(celda_ip),celda_p_enviados, celda_p_perdidos, 'ONLINE'))
                
            if not ping_equipo.success():

                
                df_registro.at[x_fila,'P. Enviados'] = int(df_registro.at[x_fila,'P. Enviados']) + 1
                df_registro.at[x_fila,'P. Perdidos'] = int(df_registro.at[x_fila,'P. Perdidos']) + 1
                
                celda_p_enviados = df_registro.at[x_fila,'P. Enviados']
                celda_p_perdidos = df_registro.at[x_fila,'P. Perdidos']
                
                tabla.delete(indices_tabla[x_fila])
                
                tabla.insert("", index=x_fila, text=str(celda_nombres), iid=str(indices_tabla[x_fila]),
                                             values=(str(celda_ip),celda_p_enviados, celda_p_perdidos, 'OFFLINE'))
            
            tabla.update()
            
            if running == False:
                break
        

    # After 1 second(1sec=1000), call scanning again (create a recursive loop)
    root.after(0, start_ping)

def start():
    """Enable scanning by setting the global flag to True."""
    global running

    running = True

    text_box.insert(END, 'START \n' + '\n'
    '--------------------------------------------------' + '\n' + '\n')
    start_ping()

def stop():
    """Stop scanning by setting the global flag to False."""
    global running
    running = False
    text_box.insert(END, 'STOP \n' + '\n'
                    '--------------------------------------------------' + '\n' + '\n')
    text_box.yview(END)

def buscar_equipos():
    
    global df_registro
    
    tabla.delete(*tabla.get_children())
    
    plantilla_registro = pd.DataFrame(columns=["NOMBRE","IP","P. Enviados", "P. Perdidos", "Ultimo Estado"])

    input_lista = pd.read_excel('LISTA_PINGS.xlsx')
    
    df_registro = pd.concat([plantilla_registro,input_lista])
    
    df_registro = df_registro[:].replace(np.nan, 0)

    lista_nombres = df_registro['NOMBRE']
    
    lista_ip = df_registro['IP']
    
    lista_p_enviados = df_registro['P. Enviados']
    
    lista_p_perdidos = df_registro['P. Perdidos']

    for x_name, x_ip, x_enviados, x_perdidos in zip(lista_nombres, lista_ip, lista_p_enviados, lista_p_perdidos):
        
        tabla.insert("", END, text=x_name,
                             values=(x_ip,x_enviados,x_perdidos))
        
        tabla.update()
        

def resetar_datos():
    
    global running
    running = False

    tabla.delete(*tabla.get_children())

root = Tk()
root.title("PROGRAMA PINGS")
root.geometry("1510x600")

app = Frame(root)

app.grid()

############
# ETIQUETA #
############

lbl_pantalla_principal =  Label(app, text="PROGRAMA PINGS",
                                   font=('Helvetica', 18, "bold"))

lbl_pantalla_principal.grid(row=0 , column=0)

#################
# BUCLE VENTANA #
#################

btn_search = Button(app, text="Buscar Equipos", command = lambda: buscar_equipos())
btn_start = Button(app, text="Start Ping!", command = lambda: start())
btn_stop = Button(app, text="Stop Ping!", command = lambda: stop())
btn_reset = Button(app, text="Resetear Datos", command = lambda: resetar_datos())



btn_search.grid(row=1 , column=0)

btn_start.grid(row=2 , column=0)

btn_stop.grid(row=3 , column=0)

btn_reset.grid(row=4 , column=0)




#########
# TABLA #
#########

tabla = ttk.Treeview(app, columns=("IP","P. Enviados", "P. Perdidos", "Ultimo Estado"))

vsb = ttk.Scrollbar(app, orient="vertical", command=tabla.yview)

vsb.grid(row=5 , column=1, sticky='NS')

tabla.configure(yscrollcommand=vsb.set)

tabla.heading("#0", text="Equipo")
tabla.heading("IP", text="IP")
tabla.heading("P. Enviados", text="P. Enviados")
tabla.heading("P. Perdidos", text="P. Perdidos")
tabla.heading("Ultimo Estado", text="Ultimo Estado")


tabla.column("#0", anchor="center", width=150, stretch=NO)
tabla.column("IP", anchor="center", width=150, stretch=NO)
tabla.column("P. Enviados", anchor="center", width=150, stretch=NO)
tabla.column("P. Perdidos", anchor="center", width=150, stretch=NO)
tabla.column("Ultimo Estado", anchor="center", width=150, stretch=NO)

tabla.grid(row=5 , column=0, sticky='NS')


###################
# CUADRO DE TEXTO #
###################


text_box = scrolledtext.ScrolledText(app, undo=True)
text_box.configure(background = 'black', fg='#ffffff')
text_box['font'] = ('consolas', '12')

text_box.grid(row=5 , column=2, sticky='NS')


#################
# BUCLE VENTANA #
#################

root.mainloop()

循环会阻止操作系统消息(事件队列),因此窗口将冻结。GUI程序中不应该有循环。如果必须有循环,则可以有线程,但不能进行任何GUI更新,但可以使用线程安全队列将信息和指令传输回主线程。@quamrana我如何做到这一点?请你能用代码写一个简单的解释吗?感谢您的代码中没有任何线程。@quamrana我尝试了3种不同的方法在代码中实现线程,结果总是完全相同的。这就是为什么我要举个例子。。。看看我做错了什么。。。谢谢你的回答