rawpython / remi

Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.
Apache License 2.0
3.53k stars 402 forks source link

Use pygal plot with Remi #243

Open shirtomatik opened 6 years ago

shirtomatik commented 6 years ago

Hello @dddomodossola,

it's me again. Remi is running great so far. Now I want to enhance my app with a chart. I wanted to create the chart with the library pygal which is a very easy plot library with output format SVG. I thought because there are already some svg widgets it should be possible to insert such a plot in my gui.

Unfortunately I can't figure out how I can show the plot and also update it during runtime. Could you please give me a hint if this should be possible and if yes, how I could do it?

Best regards!

dddomodossola commented 6 years ago

Hello @shirtomatik , pygal seems a really powerful library. You can add your graph as a standard Image widget, or as a background for a basic Widget. Have you already tried it?

dddomodossola commented 6 years ago

@shirtomatik look at this:

import remi.gui as gui
from remi import start, App
import remi.server
import os
import time
import pygal 

class PyGal(gui.Widget):
    def set_content(self, chart):
        self.data = chart.render() #_data_uri()
        i = int(time.time() * 1e6)
        self.style['background-image'] = "url('/%s/download?update_index=%d')" % (id(self), i)
        self.style['background-repeat'] = "no-repeat"
        #self.style['background-image'] = "url('data:image/svg+xml;base64,%s')"%self.data

    def download(self, update_index=0):
        print("download")
        content = self.data
        headers = {'Content-type': 'image/svg+xml'}
        return [content, headers]

class MyApp(App):
    def main(self):
        #creating a container VBox type, vertical (you can use also HBox or Widget)
        self.main_container = gui.VBox(width=300, height=300)

        self.pygal_container = PyGal(width=300, height=300)

        hist = pygal.Histogram()
        hist.add('Wide bars', [(5, 0, 10), (4, 5, 13), (2, 0, 15)])
        hist.add('Narrow bars',  [(10, 1, 2), (12, 4, 4.5), (8, 11, 13)])     
        self.pygal_container.set_content(hist)

        self.main_container.append([self.pygal_container])

        # returning the root widget
        return self.main_container

if __name__ == "__main__":
    # starts the webserver
    start(MyApp, address='127.0.0.1', port=8081, start_browser=True)
dddomodossola commented 6 years ago

even better:

import remi.gui as gui
from remi import start, App
import remi.server
import os
import time
import pygal 

class PyGal(gui.Svg):
    def set_content(self, chart):
        self.data = chart.render()
        self.add_child("chart", self.data)

class MyApp(App):
    def main(self):
        #creating a container VBox type, vertical (you can use also HBox or Widget)
        self.main_container = gui.VBox(width=300, height=300)

        self.pygal_container = PyGal(width=300, height=300)

        hist = pygal.Histogram()
        hist.add('Wide bars', [(5, 0, 10), (4, 5, 13), (2, 0, 15)])
        hist.add('Narrow bars',  [(10, 1, 2), (12, 4, 4.5), (8, 11, 13)])     
        self.pygal_container.set_content(hist)

        self.bt_test = gui.Button("change chart")
        self.bt_test.onclick.connect(self.ontest)
        self.main_container.append([self.bt_test,self.pygal_container])

        # returning the root widget
        return self.main_container

    def ontest(self, emitter):
        hist = pygal.Histogram()
        hist.add('Wide bars', [(5, 0, 10), (4, 5, 13), (2, 0, 7)])
        hist.add('Narrow bars',  [(1, 1, 1), (1, 4, 4.5), (1, 1, 13)])     
        self.pygal_container.set_content(hist)

if __name__ == "__main__":
    # starts the webserver
    start(MyApp, address='127.0.0.1', port=8081, start_browser=True)
shirtomatik commented 6 years ago

Hello @dddomodossola ,

yes I already tried some hours to get it to work. I tried to use static image and load image from svg. So in pygal I did chart.render_to_file('/tmp/chart.svg')

I also tried to use svg container, but didn't know that I just can append the svg content as child and update the content respectively. Thank you very much for this great example. I will manage it with this to integrate a chart in my app. If I've done this, I will set this thread to solved / closed.

btw: pygal is really also a very nice libary...

Thank you very much - you are the best :+1: