Python Tkinter:循环运行时窗口冻结
我什么都试过了,但我一点也不懂如何应用线程。拜托,有人能告诉我怎么做才对吗?我试过几个例子,结果总是一样的。直到“ping”循环完成,“stop”按钮才停止。请,我是一个新手,给我一个简单的解释如何应用线程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
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种不同的方法在代码中实现线程,结果总是完全相同的。这就是为什么我要举个例子。。。看看我做错了什么。。。谢谢你的回答