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”,我希望通过ping的结果来更改框,将true变成绿色false保持红色。因此,基本上,只要代码运行,我就希望它从字典中ping通,如果结果为真,我希望它更改每个框的颜色。

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

最佳答案

这是一个棘手的问题,因为当目标设备不可访问时,从OS调用的ping请求可能会有延迟。随着循环的进行,这将导致不断的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

关于python - 如何使用 Action 更改Tkinter中框的背景颜色,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50376340/

10-15 15:57