1

I want the tray icon to change according to the value of p_out. Specifically depending on its value, I want it to get a different color.

Here's the code

import pystray
import ping3

while True:
    p_out = ping3.ping("google.com", unit="ms")
    if p_out == 0:
        img = white
    elif p_out >= 999:
        img = red
    else:
        print(f'\n{p_out:4.0f}', end='')
        if p_out <= 50:
            img = green
        elif p_out <= 60:
            img = yellow
        elif p_out < 100:
            img = orange
        elif p_out >= 100:
            img = red

    icon = pystray.Icon(" ", img)
    icon.run()

I tried to 'reset' the pystray icon on every loop but it didn't work. The icon only changes when I stop and rerun the script.

  • 1
    Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Dec 26 '22 at 18:54
  • 1
    What happens when it "doesn't work"? Does the icon stay the same? Do you get an additional icon? Something else? Current behavior is part of a good [MRE], as is code that is runnable (you have undefined variables) and minimal. Your question isn't about pinging Google, so it would be best to remove that, and simply change the icon every second or something. This will narrow down where the bug is, for you and for answerers. And hey, welcome to Stack Overflow! – CrazyChucky Dec 27 '22 at 13:15

1 Answers1

5

As correctly stated in the comments, providing code that cannot run, does not help the community members to assist you. Τhe code references variables named white, red, green, yellow and orange, but these variables have not been defined or assigned values.

Despite all this, the dynamic update of the tray icon is certainly something that can be useful to others. Therefore, below you may find your code with the necessary corrections applied.

import ping3
import pystray
import threading  # Import the threading module for creating threads
from PIL import Image  # Import the Image module from PIL for creating images


def update_icon():
    while True:
        ping_output = ping3.ping("google.com", unit="ms")
        print(f'\n{ping_output:4.0f}', end='')
        if ping_output == 0:
            img = Image.new("RGB", (32, 32), (255, 255, 255))  # 32px32px, white
        elif 0 < ping_output <= 50:
            img = Image.new("RGB", (32, 32), (0, 255, 0))  # 32px32px, green
        elif 50 < ping_output <= 60:
            img = Image.new("RGB", (32, 32), (255, 255, 0))  # 32px32px, yellow
        elif 60 < ping_output < 100:
            img = Image.new("RGB", (32, 32), (255, 165, 0))  # 32px32px, orange
        elif ping_output >= 100:
            img = Image.new("RGB", (32, 32), (255, 0, 0))  # 32px32px, red
        icon.icon = img


if __name__ == "__main__":
    icon = pystray.Icon("ping")
    icon.icon = Image.new("RGB", (32, 32), (255, 255, 255))  # 32px32px, white
    # Create a new thread to run the update_icon() function
    thread = threading.Thread(target=update_icon)
    # Start the thread
    thread.start()
    icon.run()

NOTES:

  • In order to use the Image module, you must first install Pillow, with a package manager like pip, using a command like this: pip install pillow.
  • The purpose of creating a new thread -to run update_icon function- is to allow the tray icon to continue updating in the background, without blocking the main thread of execution.
  • While 32x32px is a common size for icons, it is not necessarily the only size that can be used.
  • Using a while True loop to run a continuous task can consume a large amount of system resources, such as CPU and memory, which can impact the overall performance of your program. However, I will not suggest anything about it as it is not relevant to the present question.
Andreas Violaris
  • 2,465
  • 5
  • 13
  • 26
  • How were the `if` statements "conflicting" with each other? What value could you get that would follow none of the branches? They appear to me to be comprehensive. – CrazyChucky Dec 30 '22 at 13:20
  • It appears that the `if` statements are indeed work as intended (despite the odd implementation). Thank you for pointing it out. Regarding the thread, what would you suggest instead, given that the run method is blocking? – Andreas Violaris Dec 30 '22 at 16:36
  • Based on the [results](https://i.stack.imgur.com/iCvdZ.png) of one billion executions on an independent server, I am skeptical of the efficiency you claim. Also, when it comes to efficiency and "only showing meaningful lag amounts", you don't waste resources checking for a zero ping value, which is physically impossible to get, unless you are pinging yourself. Given this, I firmly believe that readability should not be sacrificed for the sake of efficiency in this case, particularly when efficiency is not ultimately achieved. – Andreas Violaris Dec 31 '22 at 10:48
  • 1
    Furthermore, regarding the thread, you mentioned that the **run** function blocks the rest of the code. So, if I understand correctly, this means that you agree with me that you cannot call the **update_icon** function after the **run** function (and of course you can't before either, since its infinite loop will never let the **run** function to be called). This appears to be a problem, but I have not seen your proposed solution, therefore I am unable to evaluate it and provide a definite response. – Andreas Violaris Dec 31 '22 at 10:49