remi icon indicating copy to clipboard operation
remi copied to clipboard

[PySimpleGUI] Background Image for the Window

Open MikeTheWatchGuy opened this issue 6 years ago • 45 comments

I saw in the readme file this line of code:

my_widget.attributes['background-image'] = "url('/my_resources:image.png')"

It made me hopeful that I could add an image to my window "easily".

All of my windows share a similar structure. There is a "Master Widget" that contains everything. In this case, it's a remi.gui.VBox.

I attempted to perform this operation on my VBox, but it had no apparent impact, good nor bad.

self.master_widget.attributes['background-image'] = "url('{}')".format(self.window.BackgroundImage)

The string that was made when I ran my code was:

url('/res:logo.png')

I used this exact same "filename" to create an Image in my window and it worked, so the image path seems good.

MikeTheWatchGuy avatar Feb 16 '19 20:02 MikeTheWatchGuy

@MikeTheWatchGuy use .style instead of .attributes and it will work

container.style['background-image'] = "url('/my_resources:logo.png')"

dddomodossola avatar Feb 16 '19 23:02 dddomodossola

How does the image name different between this use and when it's used in a remi.gui.Image widget?

I am able to get the background image to some of the filenames that I used to make images, but some fail.

Here are some Image Elements. I add a slash to the front of these filenames before giving to your Image widget.

            [sg.Image(filename=r'e:\DownloadsE\60a1a06a9458ccd6575333e06cb42f1b-png.jpg')],
            [sg.Image(filename=r'C:\Python\PycharmProjects\GooeyGUI\Logos\PySimpleGUI Icon.png', enable_events=True, key='_IMAGE_')],
            [sg.Image(filename=r'dot:logo.jpg')],
            [sg.Image(filename=r'res:logo.png')],

Using this filename from above: r'dot:logo.jpg' Works great. I do have to add the url bit onto the front as I posted in my previous post.

What allows me to get away with c:, e:, etc is the clever static_file_path I defined.

super(Window.MyApp, self).__init__(*args, static_file_path={'C':'c:','c':'c:','D':'d:', 'd':'d:', 'E':'e:', 'e':'e:', 'dot':'.', '.':'.'})

How can I get the other 2 images to correctly display?

MikeTheWatchGuy avatar Feb 17 '19 19:02 MikeTheWatchGuy

@MikeTheWatchGuy When you setup a filename for the Image widget you don't need to speficy "url(…)" because it is an html attribute, differently when you specify a widget background you need to write "url(…)" because it is a style css property. Maybe in the future I will remove this difference. Actually, remi server accepts only requets for paths relative to the static_file_path. However you can use the already provided SuperImage class to access resources all over the entire filesystem. Do you need to setup a background image as for the SuperIMage widget? I can prepare a solution for this if you want. ;-)

dddomodossola avatar Feb 25 '19 11:02 dddomodossola

Is there a way to pass in the "contents of a file" into an Image widget instead of a filename?

One thing I use a lot in PySimpleGUI is Base64 images.

How can I display a base64 image or an image I create in RAM / read from a file into RAM?

I continue to be all messed up with these resources but haven't had time to work on them.

What I'm trying to do is make a game for Android by animating using an Image that I change frequently.

MikeTheWatchGuy avatar Apr 11 '19 22:04 MikeTheWatchGuy

Hello @MikeTheWatchGuy here is an example for you:

import remi.gui as gui
from remi import start, App
import remi.server


class MyApp(App):
            
    def main(self):
        self.main_container = gui.VBox(width=300, height=300)

        #image converted with this website: https://www.base64-image.de/encode
        self.main_container.style['background-image'] = "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAM4AAACqCAIAAABqGOffAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVMSURBVHhe7dLBjeRGEAXRdWTPMlO+yAe5tFgvJAJ9SQRmh+xi8bOYHcC7zjSzfvz499dPKcDUFGJqCjE1hZiaQkxNIcul9t/ff+3Cn+gR7k8NGQ3AP9SabksNuUyBn9BS0qkhjovgR7WCXGqoIQAfoHslUkMBYfgY3eXa1LD6jfBhyrswNYy9Anyhki5JDQMvBZ+qmPmpYdoF4YOVMTk1jLosfLYCZqaGOReHj9fVpqWGIZ8CV+g6c1LDfs+CW3SRCalhucfBObrI2dQw20PhKF3hVGoY7NFwmqYbTw1TNYADNddgahipDZypiUyNcKlmGUkN2zSDYzXL26lhmJZwsqYwtS/gZE3xXmqYpDEcrvNM7Ws4XOe9kRrGaA/n6yRT+yOcr5OOpoYZPgQeQWeY2nfwCDrD1HbgHTTsUGp4/Y+Cp9AwU9uBp9AwU9uBp9Cw/dTw9B8ID6IxprYPD6IxprYPD6IxprYPD6IxpnYI3kQDdlLDi38sPIsGmNoheBYNMLVD8CwDfvzz+xPg6srUDsGzDMAkXeHqytQOwbMMwCRd4erK1A7BswzAJF3h6srUDsGzDMAkXeHqytQOwbMMwCRd4erK1A7BswzAJF3h6srUDsGzDMAkXeHqytQOwbMMwCRd4erK1A7BswzAJF3h6montQ0e/TPhTQZgkq5wdWVq+/AgYzBJV7i6MrV9eJAxmKQrXF2Z2j48yBhM0hWurkxtHx5kDCbpCldX+6lt8PQfBU8xDJN0hasrU9uBpxiGSbrC1ZWp7cBTDMMkXeHq6lBqGwzwOfAOwzBJV7i6MrXv4BHOwCRd4erK1L6DRzgDk3SFq6ujqW0wQ3s4/yRM0hWurkztj3D+SZikK1xdvZHaBmM0hsPPwyRd4erK1L6Gw8/DJF3h6uq91DaYpCWcPAUm6QpXV6b2BZw8BSbpCldXb6e2wTDN4NhZMElXuLoyNcKxs2CSrnB1NZLaBvO0gTMnwiRd4epqMLUNRmoAB86FSbrC1dV4ahtM9Wg4bTpM0hWurk6ltsFgD4WjroBJusLV1dnUNpjtiXDRFTBJV7i6MrVEZxtM0hWuriaktsF4D4JDroNJusLV1ZzUXrDi+vD9l8IkXeHqamZqG2y5LHx2ACbpCldXk1PbYNQF4YMzMElXuLqan9oG0y4FnxqDSbrC1dUlqW0w8CLwkUmYpCtcXV2V2guWvhE+LA+TdIWrq2tTe8HqYfiYu2CSrnB1lUjtBQUE4APuhUm6wtVVLrUX1HAR/OgKMElXuLpKp/aCMibCD60Dk3SFq6t7UqvQygD8wzVhkq5wdXV/ahUa+gb+cH2YpCtcXa2VWmOYpCtcXZlaCCbpCldXphaCSbrC1ZWphWCSrnB1ZWohmKQrXF2ZWggm6QpXV6YWgkm6wtWVqYVgkq5wdWVqIZikK1xdmVoIJukKV1emFoJJusLVlamFYJKucHVlaiGYpCtcXZlaCCbpCldXphaCSbrC1ZWphWCSrnB1ZWohmKQrXF2ZWggm6QpXV6YWgkm6wtWVqYVgkq5wdWVqIZikK1xdmVoIJukKV1emFoJJusLVlamFYJKucHVlaiGYpCtcXZlaCCbpCldXphaCSbrC1ZWpKcTUFGJqCjE1hZiaQkxNIaamEFNTiKkpxNQUYmoKMTWFmJpCTE0hpqYQU1OIqSnE1BRiagoxNYWYmkJMTSGmphBTU4ipKcTUFGJqCjE1hZiaQkxNIaamEFNTiKkpxNQUYmoKMTWFmJpCTE0hpqYQU1OIqSnE1BRiagoxNYWYmkJMTSGmphBTU4ipKeLXz/8BRrNcJP9b/HYAAAAASUVORK5CYII=')"
        self.main_container.style['background-repeat'] = "no-repeat"

        bt = gui.Button("a button")
        self.main_container.append(bt)

        # returning the root widget
        return self.main_container


if __name__ == "__main__":
    # starts the webserver
    start(MyApp)

You can also play sounds with base64, like in this example

import remi.gui as gui
from remi import start, App
import os

class MyApp(App):
        
    def main(self):
        #custom js
        my_js_head = """
            <script>
                function beep(data) {
                    var snd = new Audio(data);  
                    snd.play();
                }
            </script>
            """
        self.page.children['head'].add_child('myjs', my_js_head)

        #creating a container VBox type, vertical (you can use also HBox or Widget)
        main_container = gui.VBox(width=300, height=200, style={'margin':'0px auto'})
        bt = gui.Button("play")
        bt.onclick.connect(self.on_click)
        main_container.append(bt)
        # returning the root widget
        return main_container

    def on_click(self, emitter):
        self.execute_javascript("beep('%s');"%"data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=")


if __name__ == "__main__":
    # starts the webserver
    start(MyApp)

This will help to make the game more funny :-D

dddomodossola avatar Apr 12 '19 07:04 dddomodossola

Wow! Thank you very much!!! I'll give it a try as soon as I can.... Thank you for all the quick help!

MikeTheWatchGuy avatar Apr 12 '19 19:04 MikeTheWatchGuy

I made a little function that will take my base64 variables and turn them into things that are passed to you:

def base64_to_style_image(base64_image):
    return "url('data:image/png;base64,"+base64_image+"')"

# using the func looks like this:
self.main_container.style['background-image'] = base64_to_style_image(my_image64)

THIS is really going to change a lot of possibilities for me!


Question:

What other types of "images" can I pass in? Is it possible for me to not pass a filename but instead read the contents of an image file and somehow send the contents to you? I think thinking of situations where I may "render" my own images to show an animations.

I would really like to be able to animate 2 cannons shooting arced cannon balls at each other as a simple game.

I'm trying to build a 2-play, 2-phone, Android game that people can plus using Termux and their phone. The way Remi works makes this a TRIVIAL thing to do because both players will automatically see the same screen.

MikeTheWatchGuy avatar Apr 15 '19 17:04 MikeTheWatchGuy

@MikeTheWatchGuy please give me some explanations What you mean for "type of images"?

Is it possible for me to not pass a filename but instead read the contents of an image file and somehow send the contents to you? You are not actually passing a filename, but instead the content of image, what you mean exactly?

However I suggest you to use svg elements instead of raster images. Svg elements can be animated simply, and allow better performances. I will try to provide you an example.

dddomodossola avatar Apr 16 '19 07:04 dddomodossola

@MikeTheWatchGuy here is a simple example about svg elements (it uses a physical engine called pymunk http://www.pymunk.org/en/latest/ )

import remi.gui as gui
from remi import start, App
import os
import pymunk
import random


class Ball(gui.SvgCircle):
    def __init__(self, x, y, r, *args, **kwargs):
        super(Ball, self).__init__(x, y, r, *args, **kwargs)
        mass = 10
        self.body = pymunk.Body(mass, pymunk.moment_for_circle(mass, 0, r, (0, 0)))  # Create a Body with mass and moment
        self.body.position = x,y 
        self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) # Create a box shape and attach to body
        self.shape.elasticity = 0.95
        self.shape.friction = 0.9
        
    def update(self):
        self.set_position(self.body.position[0],self.body.position[1])


class GameArena(gui.Svg):
    def __init__(self, width, height, *args, **kwargs):
        super(GameArena, self).__init__(width, height, *args, **kwargs)
        self.space = pymunk.Space()
        self.space.gravity = 0,1000

        #ground
        self.ground_body = pymunk.Body(body_type=pymunk.Body.STATIC)
        self.ground_shape = pymunk.Segment(self.ground_body, (0,height), (width,height), 0.0)
        self.ground_shape.friction = 0.9
        self.ground_shape.elasticity = 0.95
        self.space.add(self.ground_shape)

    def add_element(self, element):
        self.space.add(element.body, element.shape)   
        return self.append(element)

    def time_tick(self):
        self.space.step(0.01)
        for e in self.children.values():
            e.update()


class MyApp(App):
    def idle(self):
        self.game_arena.time_tick()

    def main(self):
        #creating a container VBox type, vertical (you can use also HBox or Widget)
        main_container = gui.VBox(style={'margin':'0px auto'})

        self.game_arena = GameArena(400,400)
        for i in range(1,100):
            x = random.randint(100,300)
            y = random.randint(100,300)
            r = random.randint(10,20)
            self.ball = Ball(x,y,r)
            self.game_arena.add_element(self.ball)
        main_container.append(self.game_arena)

        # returning the root widget
        return main_container


if __name__ == "__main__":
    # starts the webserver
    start(MyApp, address='0.0.0.0', port=0, start_browser=True, update_interval=0.01 )

funny, doesn't it? I can help you making something complex, a 2 player game

dddomodossola avatar Apr 16 '19 14:04 dddomodossola

You are FULL-ON CRAZY!

I need to see if pymunk will install on Android using termux. That's the ultimate platform I'm writing this for. I want to make not just an Android app, but one that 2 people could play and have some fun with. It's a great way to show off these Remi capabilities!

MikeTheWatchGuy avatar Apr 16 '19 14:04 MikeTheWatchGuy

@MikeTheWatchGuy Which kind of game you have in mind? Ideas:

  • tanks shooting
  • pinball
  • soldiers shooting

Why limiting to two users? You can consider N unlimited users

dddomodossola avatar Apr 17 '19 10:04 dddomodossola

I was thinking of the classic 2 stationary cannons that shoot balls in an arc. You can control the angle and thrust (use up/down buttons). This way the only thing that's moving is the balls. I was thinking I could render them in a way that I can show in my Image Element, animating by simply showing frame by frame.

I suppose it could also be done using lines of text :-) Shooting *'s that arc using lines of text, old school style.

MikeTheWatchGuy avatar Apr 18 '19 18:04 MikeTheWatchGuy

@MikeTheWatchGuy Why you don't implement Svg widgets in PySimpleGUIWeb? It would allow much better animations, and easier game development. Maybe you don't want to do it beacuse not all gui libraries supports Svg? Consider this would be a plus for PySimpleGUI respect to other libraries.

dddomodossola avatar Apr 19 '19 07:04 dddomodossola

I'll look into it. Maybe it would be good as my "Graph Element". For that element, I supply drawing primitives like lines, circles, rectangles, and images too. In tkinter they're done using "Canvas Widgets".

Is the Svg Widget similar to a Canvas or other "Drawing" type of widget?

MikeTheWatchGuy avatar Apr 19 '19 19:04 MikeTheWatchGuy

Svg widget is a container for graphical primitives, lines, circles, rectangles, polygons, text and also raster images. Svg elements are like standard widgets, they can generate events like a button. And so you can make interactive games, you can catch the click on a circle for example. Svg elements can be moved and updated in color and other attributes. Implementing svg you can embed pygal library to make powerful graphs.

dddomodossola avatar Apr 20 '19 14:04 dddomodossola

Ah! This sounds exactly like my Graph Element. Perfect! It's the element I use to make games with as I can show images inside the element along with text and other graphic elements.

I'll get to work on it right away.

I made graphs in PySimpleGUI using Matplotlib and Canvas widgets (same as my Graph elements)

I haven't tried pygal with PySimpleGUI before.

I'll work on getting my Graph element up to the point I can draw images and / or figures on it.

MikeTheWatchGuy avatar Apr 20 '19 15:04 MikeTheWatchGuy

I implemented your Svg as my Graph Element. It's a perfect match to what my Graph Element's interfaces are like.

Here's the PySimpleGUI code and what it makes. Need to add image, rectangles still.

import PySimpleGUIWeb as sg

layout = [  [sg.Text('Line Test', tooltip='Tips')],
            [sg.Graph((200,200), (0,0), (200,200), enable_events=True, key='_GRAPH_')],
            [sg.Button('Exit')]]

window = sg.Window('Window Title', layout,)

while True:             # Event Loop
    event, values = window.Read()
    print(event, values)
    if event in (None, 'Exit'):
        break
    window.Element('_GRAPH_').DrawLine((0,0), (100,100), color='red')
    window.Element('_GRAPH_').DrawLine((200,200), (100,100), color='black')
    window.Element('_GRAPH_').DrawPoint((10,150), 2, color='green')
    window.Element('_GRAPH_').DrawCircle((55,75), 30, fill_color='purple')
    window.Element('_GRAPH_').DrawText('this is my text!',(100,100))

window.Close()

image

MikeTheWatchGuy avatar Apr 20 '19 20:04 MikeTheWatchGuy

How do I move a figure in a way that deletes the previous location?

For example, I'm able to move the text in my figure from one place to another by calling .set_position, but it leaves a copy of the original still showing.

MikeTheWatchGuy avatar Apr 20 '19 20:04 MikeTheWatchGuy

I'm trying to add Images now as a drawing primitive. I've got lines, rectangles, etc. But I don't see an SvgImage object.

I tried to add an image this way:

        rpoint = remi.gui.Svg(size[0], size[1])
        rpoint.style['background-image'] = image

MikeTheWatchGuy avatar Apr 20 '19 22:04 MikeTheWatchGuy

How do I move a figure in a way that deletes the previous location? For example, I'm able to move the text in my figure from one place to another by calling .set_position, but it leaves a copy of the original still showing.

@MikeTheWatchGuy set_position is the right method to move an svg element. You see that a copy of text remains in the old position because maybe there is a copy of it in that position. I mean that, probably, you are adding the same element multiple times (in the while loop in your example) and you are calling set_position for only one instance of them. Is this correct?

In order to add a raster image to an svg element, you simply need to create a standard Image widget and append it to the svg widget ;-)

dddomodossola avatar Apr 20 '19 22:04 dddomodossola

Oh crap! I think you're right. I'm re-drawing!

Thanks for the Image tip!

Getting closer!

MikeTheWatchGuy avatar Apr 20 '19 22:04 MikeTheWatchGuy

image

I was stunned to see that my Demo Program that draws sine waves works perfectly with these new changes! The same code is running on tkinter, Qt, and Remi and makes similar looking graphs. It's crazy this stuff works!

It's located here: https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Element_Sine_Wave.py

As soon as I release my latest to PyPI I'll release some repl.its.

MikeTheWatchGuy avatar Apr 20 '19 22:04 MikeTheWatchGuy

you are a boss @MikeTheWatchGuy ;-)

dddomodossola avatar Apr 20 '19 22:04 dddomodossola

Hey, without your hands-on help, I would be worthless. YOU da man!

MikeTheWatchGuy avatar Apr 20 '19 22:04 MikeTheWatchGuy

oh wow!!! As soon as I get Images to work, I'll be able to run the Uno game in a browser!

MikeTheWatchGuy avatar Apr 20 '19 22:04 MikeTheWatchGuy

Here is an example using pygal https://github.com/dddomodossola/remi/issues/243 Now I go to sleep. Have a good development @MikeTheWatchGuy

dddomodossola avatar Apr 20 '19 22:04 dddomodossola

Can you tell me how to put a Base64 Image into an Image widget? It only takes filenames and I'm unsure how to do it other than writing as a temp file. You supplied a base64 above, but it was for a background image. I'll experiment. Maybe I just need to set the Image's background image?

MikeTheWatchGuy avatar Apr 21 '19 00:04 MikeTheWatchGuy

I only just now implemented the SuperImage class. Sorry it took SO long for me to add.

It seems to be working great for my normal images, but I'm struggling a little in placing the image inside the Svg widget at the correct location. I don't see where I can add the location to my code.

With other things that I draw like lines or circles, there's a place to put the location. Here's my latest attempt. It IS drawing an image, but it is outside of the Svd

    def DrawImage(self, image_source=None, location=(None, None), size=(100, 100), color='black', font=None, angle=0):
        if location == (None, None):
            return
        # if type(image_source) is bytes:
        #     image = base64_to_style_image(image_source)
        # else:
        # image = "url('{}')".format('/'+image_source)
        converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
        if self.Widget is None:
            print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
            print('Call Window.Finalize() prior to this operation')
            return None
        image_widget = SuperImage(image_source)
        image_widget.attributes['x'] = converted_point[0]
        image_widget.attributes['y'] = converted_point[1]
        # image_widget.style['background-repeat'] = 'no-repeat'
        self.Widget.append([image_widget,])

Here you can see that the image is outside of the light blue Svg box.

image

MikeTheWatchGuy avatar Apr 21 '19 00:04 MikeTheWatchGuy

And here's a repl.it that has my code and the demo program.

https://repl.it/@PySimpleGUI/Drawing-Primitives-using-Remis-Svg-Widget

If you click the Draw button, it'll draw a bunch of stuff in the blue box.

If you click Image, it's supposed to draw the image inside of the blue box, but instead it's to the right of the box.

MikeTheWatchGuy avatar Apr 21 '19 01:04 MikeTheWatchGuy

Here's my "Draw Image" code.

No matter what I try, the image is always added to the right of the Svg light blue square. I want it to be drawn inside the square.

self.Widget, by the way, is my remi.gui.Svg object, not a Remi Widget. You've seen this bad thing in my code before :-) Just reminding you I'm still bad.

    def DrawImage(self, image_source=None, location=(None, None), size=(100, 100), color='black', font=None, angle=0):
        if location == (None, None):
            return
        # if type(image_source) is bytes:
        #     image = base64_to_style_image(image_source)
        # else:
        # image = "url('{}')".format('/'+image_source)
        converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
        if self.Widget is None:
            print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
            print('Call Window.Finalize() prior to this operation')
            return None
        image_widget = SuperImage(image_source)
        shape = remi.gui.SvgShape(converted_point[0], converted_point[1])
        shape.append([image_widget,])
        self.Widget.append([shape,])

MikeTheWatchGuy avatar Apr 21 '19 21:04 MikeTheWatchGuy