将 Gnuplot 打印到 Kivy 小部件

Posted

技术标签:

【中文标题】将 Gnuplot 打印到 Kivy 小部件【英文标题】:Print Gnuplot to Kivy Widget 【发布时间】:2019-05-08 20:55:26 【问题描述】:

我正在寻找实现这个 MWE:

https://***.com/a/44922317/6924364

但是使用 Gnuplot,类似这样:

https://***.com/a/21633082/6924364

如何将 Gnuplot 输出传递到 Kivy 应用程序,并显示图像而无需在本地保存?


编辑 1:这是一个 MWE,只需要一些代码即可将图像对象添加到自定义小部件,但我不确定如何完成。

from subprocess import Popen, PIPE
from StringIO import StringIO                                            
from io import BytesIO
from os import linesep as nl
from PIL import Image as Image

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.core.image import Image as CoreImage


def gnuplot(commands, data):                                                    
    """ drive gnuplot, expects lists, returns stdout as string """              

    dfile = StringIO()                                                          
    for line in data:                                                           
        dfile.write(str(line) + nl)                                             

    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]            
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)                       

    dfile.seek(0)                                                               
    return p.communicate(dfile.read())[0]   


def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal png",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]

    return (commands, data)


class Plot(Widget):

    (commands, data) = gnuplot_GifTest()
    img = BytesIO(gnuplot(commands,data))
    anImg = CoreImage(img,ext="png")

    def __init__(self,**kwargs):
        super(Plot,self).__init__(**kwargs)

        # HMM, how to display self.anImg??
        print self.anImg

class MyApp(App):

    def build(self):
        box = BoxLayout(orientation="vertical")
        box.add_widget(Plot())
        return box

MyApp().run()

【问题讨论】:

我取得了一些进展,发现在第二个MWE中,输出的StringIO可以转换为考虑***.com/a/23489503/6924364的对象。我很快就会发布一个完整的 MWE 集成到 kivy 中。 在这个 MWE 上取得了更多进展:***.com/a/52340135/6924364。现在,合成所有这些代码。 MWE 添加到原帖中。 我找到了解决方案! ***.com/a/37279624/6924364 此参考资料也可能与未来的读者相关;我没有复制其中完成的内容,但是拥有一个自动 gnu 绘图的 kivy 库会很酷:github.com/kivy-garden/garden.matplotlib/blob/master/… 【参考方案1】:

经过一番研究,我找到了解决问题的方法。如果有其他解决方案,我会在周末向其他读者开放。

from subprocess import Popen, PIPE
from StringIO import StringIO                                            
from io import BytesIO
from os import linesep as nl
from PIL import Image as Image

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.core.image import Image as CoreImage
from kivy.uix.image import Image as UIXImage

def gnuplot(commands, data):                                                    
    """ drive gnuplot, expects lists, returns stdout as string """              

    dfile = StringIO()                                                          
    for line in data:                                                           
        dfile.write(str(line) + nl)                                             

    args = ["gnuplot", "-e", (";".join([str(c) for c in commands]))]            
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)                       

    dfile.seek(0)                                                               
    return p.communicate(dfile.read())[0]   


def gnuplot_GifTest():
    commands = [\
        "set datafile separator ','",\
        "set terminal gif",\
        "set output",\
        "plot '-' using 1:2 with linespoints, '' using 1:2 with linespoints",\
        ]
    data = [\
        "1,1",\
        "2,2",\
        "3,5",\
        "4,2",\
        "5,1",\
        "e",\
        "1,5",\
        "2,4",\
        "3,1",\
        "4,4",\
        "5,5",\
        "e",\
        ]

    return (commands, data)


class Plot(UIXImage):

    def __init__(self,commands,data,**kwargs):
        super(Plot,self).__init__(**kwargs)
        gnu_img = BytesIO(gnuplot(commands,data))
        gnu_converted = CoreImage(gnu_img,ext="gif")
        self.texture = gnu_converted.texture


class MyApp(App):

    def build(self):
        (commands, data) = gnuplot_GifTest() # example for passing gnuplot commands and data to the plot widget
        box = BoxLayout(orientation="vertical")
        box.add_widget(Plot(commands,data))
        return box

MyApp().run()

【讨论】:

以上是关于将 Gnuplot 打印到 Kivy 小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何将位于同一行的 Kivy 小部件移得更远?

向 Kivy 添加小部件时如何确保功能正常

Kivy HELP:小部件和屏幕管理器

Kivy 在布局末尾添加小部件

如何传递一个值来初始化 Kivy 中的屏幕小部件?

如何从 kivy 小部件画布中删除特定说明?