7

I have Python GUI using PySimpleGUI that needs to display multiple plots which I intend to navigate via a set of buttons. I know I can have all the plots saved as PNG in a given folder and simply load them in a Image object and use the Update method of the element to load a new image when a button is clicked.

Something like the below works well:

[sg.Image(filename=os.getcwd() + pngFileName, key='key1', size=(5, 6))]

where I need to pass a filename of the plot I want to read from my current directory and show in the Image widget.

But this means that I will have all the files saved in a folder while I would rather prefer to have all the PNGs in a dictionary and refer that dictionary when I need to pass a given filename to the sg.Image().

The advantage I see is that this way I don't have to occupy space on the hard drive to store the PNGs and also instead of having to write and then read from disk, I guess it will be faster to get the PNGs directly from the dictionary that is in memory at run time.

I am not able to achieve this as the code seems to expect a filename that has a specific path rather than passing a specific value of a dictionary containing PNGs.

How can I achieve this?

opt
  • 477
  • 1
  • 10
  • 25
  • What format are your plots in? Where are the images originating specifically? Are they coming from Matplotlib or something like that? You will be able to update the image element with the in-ram versions of the images. – Mike from PSG Nov 08 '19 at 23:25
  • Did you tried implementing the image layout ? like layout = [ [sg.Image(r'Logo_320.png')],] – champion-runner Nov 13 '19 at 09:43

2 Answers2

1

Question: Use PNG files from a dictionary to display in a Image widget in PySimpleGUI (Python)


The class Image is defined as:

class Image(Element):
    def __init__(self, filename=None, data=None, ...):
        """
        :param filename:  (str) image filename if there is a button image. 
                          GIFs and PNGs only.
        :param data:      Union[bytes, str] Raw or Base64 representation of the image
                          to put on button. 
        Choose either filename or data     

You can do:

import PySimpleGUI as sg
import os

cwd = os.getcwd()
fname = 'image1.png'

with open('{}/{}'.format(cwd, fname)) as fh:
    image1 = fh.read()

[sg.Image(data=image1, key='key1', size=(5, 6))]

Something like this should work (assuming two images:image1, image2):


import PySimpleGUI as sg
# All the stuff inside your window.
layout [
         [sg.Image(data=image1, key='__IMAGE__', size=(5, 6))]
       ]

# Create the Window
window = sg.Window('Window Title', layout)

# Event Loop to process "events" and get the "values" of the inputs
while True:
    event, values = window.read()
    if event in (None, 'Cancel'):   # if user closes window or clicks cancel
        break

    window.Element('_IMAGE_').Update(data=image2)

window.close()
stovfl
  • 14,998
  • 7
  • 24
  • 51
1

One of the Demo Programs listed on the PySimpleGUI GitHub is Demo_Img_Viewer.py. In it you'll find a function that takes a filename and returns the data that you can pass to the update method of your Image element.

This function is part of that demo. It will render a file into the format that the update method expects.

from PIL import Image

def get_img_data(f, maxsize=(1200, 850)):
    """
    Generate image data using PIL
    """
    img = Image.open(f)
    img.thumbnail(maxsize)
    bio = io.BytesIO()
    img.save(bio, format="PNG")
    del img
    return bio.getvalue()

You can loop through your files and "pre-render" them by calling this function and saving the results.

Then later you can update your image element with one of these pre-rendered images.

window['My Image Element Key'].update(data=rendered)

Mike from PSG
  • 5,312
  • 21
  • 39