Comment changer la couleur d'arrière-plan de la boîte dans Tkinter avec une action
import platform
import subprocess
from tkinter import *
###IPs to use
iptoscan = {
'test': '8.8.8.8',
'test 2' : '7.7.7.7',
'test 3' : '1.1.1.1'
}
###Ping function
def ping(ipAddr: object, timeout: object = 100) -> object:
if platform.system().lower() == 'windows':
numFlag = '-n'
else:
numFlag = '-c'
global completedPing
completedPing = subprocess.run(['ping', numFlag, '1', '-w', str(timeout), ipAddr],
stdout=subprocess.PIPE, # Capture standard out
stderr=subprocess.STDOUT) # Capture standard error
if completedPing.returncode == 0: # I need this if command to send the IP address and a True command
pingstatus = "Network Active " # Active ping response
else: # I need this to send the IP plus a False command
pingstatus = "Network Error " # No ping response
print(pingstatus + ipAddr)
return (completedPing.returncode == 0) and (b'TTL=' in completedPing.stdout)
###Function to ping from dictionary
def multiping():
for ips in iptoscan:
ping(iptoscan[ips])
if completedPing.returncode == 0:
return True
else:
print("notworking")
Ma question
Au lieu d'utiliser un "ButtonPress", je veux que les cases changent avec le résultat du ping, true devient vert faux reste rouge. Donc, fondamentalement, dès que le code s'exécute, je veux qu'il envoie un ping du dictionnaire et si les résultats sont vrais, je veux qu'il change la couleur de chaque boîte.
class OneSquare():
def __init__(self, can, start_x, start_y, size):
self.can=can
self.id = self.can.create_rectangle((start_x, start_y,
start_x+size, start_y+size), fill="red")
self.can.tag_bind(self.id, "<ButtonPress-1>", self.set_color)
self.color_change=True
def set_color(self, event=None):
self.color_change = not self.color_change
color="red"
if not self.color_change:
color="green"
self.can.itemconfigure(self.id, fill=color)
root = Tk()
canvas = Canvas(root)
canvas.grid(column=1, row=1, sticky=(N, S, E, W))
#Boxes to display the network status
IP1=OneSquare(canvas, 1, 1, 30)
IP2=OneSquare(canvas, 1, 50, 30)
IP3=OneSquare(canvas, 1, 100, 30)
#Exit button
Button(root, text="Exit", bg="orange",
command=root.quit).grid(row=2)
multiping()
root.mainloop()
Ce sont des questions un peu délicates car les requêtes ping appelées à partir du système d'exploitation peuvent avoir des retards lorsque le périphérique de destination est inaccessible. Cela entraînera des gels constants de tkinter et des retards dans votre programme au fur et à mesure de la boucle. Pour éviter de tels scénarios, le moyen le plus simple est d'utiliser des threads (dont tkinter n'aime pas).
Vous auriez besoin d'un thread séparé qui effectue ces requêtes en permanence et se termine lorsque tkinter le fait. Assurez-vous que vous n'effectuez aucun appel de ce thread vers vos widgets, car cela entraînera des erreurs inattendues et des plantages.
Voici un exemple simple que vous pouvez appliquer à votre code:
import subprocess, time
from tkinter import *
from threading import Thread
iptoscan = { # Your IP list
'test': '8.8.8.8',
'test 2' : '7.7.7.7',
'test 3' : '1.1.1.1'
}
def startPing():
while root:
for id in iptoscan:
process = subprocess.Popen(['ping', iptoscan[id], '-n', '1'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # This is just for windows OS (the system i'm testing on), -n 1 if for sending only one ping request
#labels[id][1] = process.stdout.read().split('\r\n')[2] # for python 2.x
labels[id][1] = str(process.stdout.read()).split('\\r\\n')[2]
time.sleep(1) # Delay between ping requests
def updateLabels():
for id in labels:
if 'time=' in labels[id][1]: # This could be our trigger for knowing if ping was successful
labels[id][0].configure(bg = 'green', text = 'IP: ' +iptoscan[id] + ', time: ' + labels[id][1].split('time=')[1].split(' ')[0] ) # I'm updating the names also as you can see
else:
labels[id][0].configure(bg = 'dark orange', text = 'IP: ' +iptoscan[id] + ' ' +labels[id][1] ) # If the requst fails, display the message
root.after(100, updateLabels) # Continue the loop
root = Tk()
root.geometry('300x120')
labels = {} # We'll store the label widget and ping response in this dictionary
for id in iptoscan:
label = Label(root, text = 'IP: ' + iptoscan[id] )
label.pack(side='bottom',pady=10)
labels[id] = [label, ''] # First element will be the widget and second one the response
Thread(target = startPing).start() # Starting the thread to perform ping requests
root.after(100, updateLabels) # Starting to loop the function that will update ping responses to our widgets
root.mainloop()
root = None