#python #multithreading #tkinter
#python #многопоточность #tkinter
Вопрос:
Я перепробовал все, но я вообще не понимаю, как применять потоки. Пожалуйста, кто-нибудь может подсказать мне, как это сделать правильно? Я пробовал несколько примеров, и результат всегда один и тот же. Кнопка «стоп» не останавливается, пока цикл «ping» не завершится. Пожалуйста, я новичок, дайте мне простое объяснение того, как применить поток
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()
Комментарии:
1. Цикл блокирует сообщения ОС (очередь событий), поэтому окно зависает
2. В программе с графическим интерфейсом не должно быть циклов. Если у вас должны быть циклы, тогда у вас могут быть потоки, но тогда вы не сможете выполнять какие-либо обновления графического интерфейса, но вы можете использовать потокобезопасные очереди для передачи информации и инструкций обратно в основной поток.
3. @quamrana Как я могу это сделать? пожалуйста, вы можете написать простое объяснение с помощью кода? Спасибо
4. кстати, в вашем коде нет потоков.
5. @quamrana Я пробовал 3 разных способа реализации потоков в коде, и результат всегда один и тот же. Вот почему я прошу пример … чтобы увидеть, что я делаю неправильно… Спасибо за ответ