如何使用操作

时间:2018-05-16 16:57:18

标签: python tkinter

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

1 个答案:

答案 0 :(得分:1)

这是一个有点棘手的问题,因为当目标设备无法访问时,从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