Forum Archive

How to put icons in...

Peter S

Hi,

I'm new to Python and to Pythonista. I'm working on a program that fetches data and put the results in a view. I made a design in the UI Editor, it consists labels for textual results and Image Views for icons.

My problem is to put icons in the Image Views. I have a map consisting gifs. An ImageView icon points to the IOS images like alert_24 (the !). Can I redirect it to my map of gifs?

To put text in a label I use: v['label1'].text = placeDate
Can I do something similar to put icon therm.gif in imageview9?

Thank you very much for your help,

Peter

cvp

@Peter-S that works with jpg and png, perhaps not with gif

v['imageview9'].image = ui.Image.named('your file')

sometimes needs

v['imageview9'].image = ui.Image.named('your file').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)

For gif, see also here

Peter S

@cvp It works! With gifs as well. Thank you very much, your answer was very clear.

cvp

@Peter-S For animated gif, see also here

Peter S

@cvp The result: https://scheelpj.home.xs4all.nl/Weer.jpg

Thanks again!

cvp

@Peter-S Nice 👍
You can include your image in your post with

cvp

@Peter-S Try this, you only have to change a few things in your script and you'll even display your gifs as animated

import ui
import io
from PIL import Image

class GifInImageView(ui.View):
    def __init__(self,imageview,gif_file,duration=1):
        self.duration = duration
        self.ImageView = ui.ImageView()
        self.add_subview(self.ImageView)
        self.pil = Image.open(gif_file)
        wi,hi = self.pil.size
        wiv = imageview.width
        hiv = wiv * hi / wi
        self.frame = (0,0,wiv,hiv)
        imageview.add_subview(self)
        self.update_interval = self.duration / self.pil.n_frames
        self.frame_id = 0
    def pil2ui(self,imgIn):
        with io.BytesIO() as bIO:
            imgIn.save(bIO, 'PNG')
            imgOut = ui.Image.from_data(bIO.getvalue())
        del bIO
        return imgOut
    def update(self):
        # Display individual frames from the loaded animated GIF file
        self.pil.seek(self.frame_id)
        self.ImageView.image = self.pil2ui(self.pil)
        self.ImageView.content_mode = ui.CONTENT_SCALE_ASPECT_FIT
        self.frame_id = self.frame_id + 1
        if self.frame_id >= self.pil.n_frames:
            self.frame_id = 0
    def touch_ended(self,touch):
        if self.update_interval == 0:
            self.update_interval = self.duration / self.pil.n_frames
        else:
            self.update_interval = 0

if __name__ == '__main__':
    v = ui.load_view('test3')

    #v['imageview1'].image = ui.Image.named('meteo1.gif')
    GifInImageView(v['imageview1'],'meteo1.gif',duration=1)
    #v['imageview2'].image = ui.Image.named('meteo2.gif')
    GifInImageView(v['imageview2'],'meteo2.gif',duration=3)

    v.present('sheet')

Peter S

@cvp Thank you for both tips. The second one would make it possible to see the raindrops fall. I’ll think about that 😀

cvp

@Peter-S If you have real .gif, you don't have a lot to do to test it. Only copy the GifInImageView class and replace some lines

v['imageview1'].image = ui.Image.named('meteo1.gif')

By

 GifInImageView(v['imageview1'],'meteo1.gif',duration=1)
cvp

As the .Gif file contains the duration of each frame, my little script has been modified because the duration parameter is not needed.
Name of class and view parameter are also modified because the view in which the gif will be displayed may be any View, not only an ImageView.
I also remove the touch_ended method because it is not needed here.
Sorry for these modifications, I had posted too quickly, just to be sure I'd not forget, I've a so bad memory 😢

import ui
import io
from PIL import Image

class GifInView(ui.View):
    def __init__(self,view,gif_file):
        self.ImageView = ui.ImageView()
        self.add_subview(self.ImageView)
        self.pil = Image.open(gif_file)
        wi,hi = self.pil.size
        wiv = view.width
        hiv = wiv * hi / wi
        self.frame = (0,0,wiv,hiv)
        view.add_subview(self)
        # In a GIF file, each frame has its own duration
        # assume here all frames have the same duration 
        self.update_interval = self.pil.info['duration']/1000
        self.frame_id = 0
    def pil2ui(self,imgIn):
        with io.BytesIO() as bIO:
            imgIn.save(bIO, 'PNG')
            imgOut = ui.Image.from_data(bIO.getvalue())
        del bIO
        return imgOut
    def update(self):
        # Display individual frames from the loaded animated GIF file
        self.pil.seek(self.frame_id)
        self.ImageView.image = self.pil2ui(self.pil)
        self.ImageView.content_mode = ui.CONTENT_SCALE_ASPECT_FIT
        self.frame_id = self.frame_id + 1
        if self.frame_id >= self.pil.n_frames:
            self.frame_id = 0

if __name__ == '__main__':
    v = ui.load_view('test3')

    GifInView(v['imageview1'],'meteo1.gif')
    GifInView(v['imageview2'],'meteo2.gif')

    v.present('sheet')
Peter S

@cvp I pasted class GitToView into my program, made an imageview, downloaded an animated gif and displayed it. It works, the animation runs fine. But...

The gif is about 450 x 450 px, the imageview as well, the displayed version is about one/third of the original. When I move the x,y of the imageview, the gif moves with it.

I don't understand what happens in the class, so I can't solve the problem. Can you point out what I'm doing wrong? Thanks.

cvp

@Peter-S Sorry, it I don't really understand... Could you post the needed files: py, pyui if needed, gif url

Peter S

Part of the py:

class GifInView(ui.View):
    def __init__(self,view,gif_file):
        self.ImageView = ui.ImageView()
        self.add_subview(self.ImageView)
        self.pil = Image.open(gif_file)
        wi,hi = self.pil.size
        wiv = view.width
        hiv = wiv * hi / wi
        self.frame = (0,0,wiv,hiv)
        view.add_subview(self)
        # In a GIF file, each frame has its own duration
        # assume here all frames have the same duration 
        self.update_interval = self.pil.info['duration']/1000
        self.frame_id = 0
    def pil2ui(self,imgIn):
        with io.BytesIO() as bIO:
            imgIn.save(bIO, 'PNG')
            imgOut = ui.Image.from_data(bIO.getvalue())
        del bIO
        return imgOut
    def update(self):
        # Display individual frames from the loaded animated GIF file
        self.pil.seek(self.frame_id)
        self.ImageView.image = self.pil2ui(self.pil)
        self.ImageView.content_mode = ui.CONTENT_SCALE_TO_FILL
        self.frame_id = self.frame_id + 1
        if self.frame_id >= self.pil.n_frames:
            self.frame_id = 0


# knop regenradar
def knopje(sender):
    uri = 'https://api.buienradar.nl/image/1.0/radarmapnl/gif/?hist=0&forc=36&width=550&l=1&step=1'
    with open('./gif/radar.gif', 'wb') as f:
        f.write(requests.get(uri).content)
    r = ui.load_view('Radar')
    if ui.get_screen_size()[1] >= 768:
        r.present('sheet')
    else:
        r.present()
    GifInView(r['imageview1'],'./gif/radar.gif')

The link to the gif:
link text

The result is an animated gif displayed, but too small for the imageview (about 1/4th).

cvp

@Peter-S As I don't have your .pyui file, I can reproduce the problem with

# knop regenradar
def knopje(sender):
    #uri = 'https://api.buienradar.nl/image/1.0/radarmapnl/gif/?hist=0&forc=36&width=550&l=1&step=1'
    #with open('radar.gif', 'wb') as f:
    #    f.write(requests.get(uri).content)
    #r = ui.load_view('Radar')
    r = ui.View()
    r.frame = (0,0,600,600)
    imageview1 = ui.ImageView(name='imageview1')
    imageview1.frame = (10,10,450,450)
    imageview1.border_width = 1
    r.add_subview(imageview1)
    if ui.get_screen_size()[1] >= 768:
        r.present('sheet')
    else:
        r.present()
    GifInView(r['imageview1'],'IMG_6928.GIF')

knopje('test')

I search the origin but don't find actually, wait and hope 😀

Peter S

Here the same result with your code for the imageview. When I bypass GifInView and load a png in my pyui with r['imageview1'].image = ui.Image.named('./gif/image.png'), the picture fills the whole frame.

Succes, looking forward to a solution!

cvp

@Peter-S Found, shame on me 😔, sorry, put this line after self.frame = ...

        self.ImageView.frame = self.frame

Delay has been long because I've problems of response time with the forum site

Peter S

Fantastic view from wall to wall. Thank you very much!
And you're right, the site is pretty slow. Nevertheless, good answers are always in time...

cvp

@Peter-S I am so ashamed that I think I will change my username to hide me in the forum 🤭

Peter S

@cvp Of course not, the whole code worked, it only needed a bit of pumping up the image. Thanks again!