Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update/change Icon.image while it is running #68

Closed
boramalper opened this issue Oct 7, 2020 · 3 comments
Closed

Update/change Icon.image while it is running #68

boramalper opened this issue Oct 7, 2020 · 3 comments

Comments

@boramalper
Copy link

Hi,

Thank you for your great work! I was trying to figure out how to update/refresh/change icon image while run() has already been called on Icon (i.e. while it is running). Ideally, I would love to do this periodically (say, every 5 minutes), but in the worst case, triggering it from a MenuItem callback is also okay.

Is this possible with pystray?

Thanks again!

@moses-palmer
Copy link
Owner

Thank you for your report.

Yes, this is possible. Simply assign to Icon.icon like this:

import sys
from PIL import Image, ImageDraw

from pystray import Icon, Menu as menu, MenuItem as item


clicks = []


def image(color1, color2, width=64, height=64):
    image = Image.new('RGB', (width, height), color1)
    dc = ImageDraw.Draw(image)

    dc.rectangle((width // 2, 0, width, height // 2), fill=color2)
    dc.rectangle((0, height // 2, width // 2, height), fill=color2)

    return image


def on_activate(icon):
    clicks.append(icon)

    if len(clicks) == 5:
        icon.stop()
    else:
        icon.icon = images[len(clicks) % len(images)]


images = (image('white', 'black'), image('black', 'white'))
icon = Icon(
    'test',
    icon=images[0],
    menu=menu(item('Toggle ', on_activate)))

icon.run()

@namashin
Copy link

Hi, Thank for good example!!!

I want to change tasktray icon by time.
For example.

Every 1 seconds , example.ico change to example2.ico, and change to example3.ico and so on.

I made TCP/IP connection Server and i want to cancel TCP connection by putting tasktray ico, while connecting Client and Server, icon change every 1 seconds.

Is there any way to solve this question???

      class TaskTrayOperator(object):
          def __init__(self, finish_TCP_connection_function):
              self.finish_gw = finish_TCP_connection_function
      
              # set icon image 
              self.images = (Image.open('gw.ico'), Image.open('gw2.ico'), Image.open('gw3.ico'),
                        Image.open('gw4.ico'), Image.open('gw5.ico'))
      
              # change icon by time
              self.timer = 0
      
              # tasktray menu
              menu = Menu(MenuItem('FINISH', self.on_activate))
      
              self.icon = Icon(
                  'Gateway',
                  icon=self.images[0],
                  menu=menu)
      
              # blocking here
              self.icon.run()
      
          def quit_gateway(self):
              self.finish_gw()
      
          def on_activate(self):
              if self.timer == 5:
                  self.timer = 0
      
              self.icon.icon = self.images[self.timer]
              self.timer += 1
      
      
      def finish_gw():
          print("finish gw")
      
      
      if __name__ == '__main__':
          S = TaskTrayOperator(finish_gw)

Thank you

@woodzzzzzz
Copy link

It's an old thread but I found a workaround by using recursion to call a function that checks a condition periodically (10 seconds): if true it restarts the icon with an image , if false it restarts with another one.

#!/usr/bin/env python

from PIL import Image
import pystray

from time import sleep
import subprocess
import os 

dir_path = os.path.dirname(os.path.realpath(__file__))
connected_img = Image.open(dir_path+'/connected.png') # the "connected" image path
disconnected_img = Image.open(dir_path+'/disconnected.png') # the "disconnected" image path



def get_file_content():
    ## retrieves the content of /etc/resolv.conf
    output = subprocess.check_output(['cat','/etc/resolv.conf']).decode('utf-8')
    return output


def change_img(ico):
    #checks if /etc/resolv.conf contains the string ProtonVpn, if true changes the visible icon
    ico.visible=False
    ico.icon=(connected_img if "ProtonVPN" in get_file_content() else disconnected_img)
    ico.visible=True
    sleep(10) # interval between checks if connected to vpn
    ico.run(setup=change_img) #this is used for recursively call the change_img function

def on_clicked(icon,item):
    #exits the application, this is used to stop the application from within a thread.
    os._exit(0)


exit_menu = pystray.MenuItem('exit vpn checker',on_clicked)

ico = pystray.Icon("vpn connection checker",icon=disconnected_img,
                   menu=pystray.Menu(exit_menu) 
                   )

ico.run(setup=change_img)

if you get a error saying AttributeError: module 'PIL.Image' has no attribute 'ANTIALIAS' please check this https://stackoverflow.com/questions/76616042/attributeerror-module-pil-image-has-no-attribute-antialias

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants