Как изменить цвет фона коробки в Tkinter с помощью действия - PullRequest
0 голосов
/ 16 мая 2018
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")

Мой вопрос
Вместо использования «ButtonPress» я хочу изменить поля с результатом пинга, true становится зеленым, false остается красным. Таким образом, в основном, как только код запускается, я хочу, чтобы он пинговал из словаря, и если результаты верны, я хочу, чтобы он менял цвет каждого поля.

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()

1 Ответ

0 голосов
/ 16 мая 2018

Это немного хитрый вопрос, потому что запросы на пинг, вызываемые из ОС, могут задерживаться, когда целевое устройство недоступно.Это приведет к постоянному зависанию tkinter и задержкам в вашей программе во время цикла.Чтобы избежать таких сценариев, самый простой способ - использовать потоки (которые tkinter не любит).

Вам потребуется отдельный поток, который постоянно выполняет эти запросы и завершает работу, когда tkinter это делает.Убедитесь, что вы не делаете никаких вызовов из этого потока в ваши виджеты, так как это приведет к неожиданным ошибкам и сбоям.

Вот простой пример, который вы можете применить к своему коду:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...