带有MeshLinePlot混淆的Python Kivy图 [英] Python Kivy Plots with MeshLinePlot confusion

查看:66
本文介绍了带有MeshLinePlot混淆的Python Kivy图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为Kivy应用程序实现测量的实时绘图,但是我不了解Kivy Garden库的内部工作原理.

I am trying to implement real time plots for measurements to a Kivy application, but I do not understand the inner workings of the kivy garden library.

我要实现的目标:我想在ScrollView中包含多个图,以便可以从字典中以编程方式添加多个实时图,并在它们占据更多空间时滚动浏览它们.空间超过一个屏幕的高度.我的主要问题是,Graph的行为不像普通的Widget,而是行为像画布.我已经尝试使用matplotlib作为backend_kivyagg来实现这一点,但是我无法为每个

My goal that I want to achieve: I want to have multiple plots inside a ScrollView such that I can add multiple real time plots programmatically from a dictionary and scroll through them if they occupy more space than one screen height. The main problem I have is that the Graph does not behave like an ordinary Widget but rather behaves like a canvas. I already tried to implement this with matplotlib as backend_kivyagg, but I failed to have fixed size for every subplot that I created.

我不知道有多件事,为什么会像它们一样发生.

There are multiple things that I do not understand why they happen like they happen.

from math import sin, cos

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.widget import Widget

from kivy.garden.graph import Graph, MeshLinePlot


class Plot(Widget):
    def __init__(self):
        super(Plot, self).__init__()
        self.graph = Graph(xlabel="x", ylabel="y", x_ticks_minor=5, x_ticks_major=25, y_ticks_major=1,
                           y_grid_label=True, x_grid_label=True, x_grid=True, y_grid=True,
                           xmin=-0, xmax=100, ymin=-1, ymax=1, draw_border=False)
        # graph.size = (1200, 400)
        # self.graph.pos = self.center

        self.plot = MeshLinePlot(color=[1, 1, 1, 1])
        self.plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
        self.plot2 = MeshLinePlot(color=[1, 0, 0, 1])
        self.plot2.points = [(x, cos(x / 10.)) for x in range(0, 101)]
        self.add_widget(self.graph)

        self.graph.add_plot(self.plot)
        self.graph.add_plot(self.plot2)


class GraphLayoutApp(App):

    def build(self):
        scroll_view = ScrollView()
        grid_layout = GridLayout(cols=1, row_force_default=True, padding=20, spacing=20)
        graph = Plot()
        graph2 = Plot()
        label = Label(text="Hello World!")
        label2 = Label(text="Hello World!")
        grid_layout.add_widget(label)
        grid_layout.add_widget(graph)
        grid_layout.add_widget(label2)
        grid_layout.add_widget(graph2)
        scroll_view.add_widget(grid_layout)

        return scroll_view


if __name__ == '__main__':
    GraphLayoutApp().run()

问题:

  1. 在GraphLayoutApp类中,我创建了两个对象graph和graph2,但是如果将它们添加到GridLayout()中,则只会出现一个对象吗?如何 我可以添加多个图形吗?

  1. Inside the class GraphLayoutApp I create two objects graph and graph2 but if I add them to the GridLayout() only one does appear? How can I add multiple graphs?

也在类GraphLayoutApp的build方法中,我创建了两个标签.我想先显示第一个label然后是图形 然后是第二个标签label2.但在我看来,该图 总是显示在左下角.我想这是必须要做的 用它在上面绘制的画布来绘制,但我无法解决.

Also Inside the build method of the class GraphLayoutApp I create two lables. I wanted to first display the first label then the graph and then the second label label2. But it seems to me that the graph is always displayed in the lower left corner. I guess this has to do with the canvas on which it is drawn, but I cannot solve it.

推荐答案

以下是修正的版本,已修复了一些问题:

Here is a modified version with some things fixed:

这里的问题是您使Plot从Widget继承而来,该Widget实际上是框架中最基本的Widget,并且由于它不是布局,因此无法管理添加到其中的子项中的任何内容,因此添加到它的窗口小部件保留默认大小/位置(分别为[100,100]和[0,0]),因此它们彼此堆叠,我使用了RelativeLayout,它默认将子级设置为其自己的大小和位置,因此Graph跟随小部件.另一个解决方案是简单地使Plot从Graph继承,因为它是唯一的子级,并使用"self.add_plot"而不是"self.graph.add_plot",并覆盖Graph参数,最好的解决方案可能是创建一个绘图类的KV规则.但是第一个解决方案是对您的代码进行最小的更改.

The issue here is that you made your Plot inherit from Widget, which really the most basic widget in the framework, and as it's not a layout, doesn't manage anything in the children you add to it, so the Graph widget you added to it was left at the default size/position (respectively [100, 100] and [0, 0]), and so they stacked on each others, i used RelativeLayout, which sets children by default to its own size and position, so the Graph follows the widget. Another solution is to simply make Plot inherit from Graph, since it's the only child, and to use "self.add_plot" instead of "self.graph.add_plot", and to override the Graph parameters, the best solution is probably to create a KV rule for the Plot class. But the first solution was the minimal change from your code.

您错过的一般原则是,在奇异果中,小部件默认情况下不受任何位置/大小的约束,除非它们的父级是专门管理此布局的布局(如GridLayout为您的标签所做的那样).

The general principle you missed is that in kivy, widgets are by default not constrained to any position/size, unless their parents are layouts that specifically manage that (like GridLayout did for your labels).

我还使GridLayout自动将其自身大小调整为minimum_size(由我在所有小部件中放入的硬编码大小确定),因此实际上您需要滚动一些内容.

I also made the GridLayout automatically size itself to the minimum_size (determined by the hardcoded size i put in all widgets), so you actually have something to scroll on.

这段代码也是由python驱动的,从本质上来说,您通常希望使用KV而不是对静态内容使用add_widget做更多的事情.

This code is also very python-driven, in kivy, you usually want to do more things using KV, rather than using add_widget for static things.

from math import sin, cos

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.widget import Widget
from kivy.uix.relativelayout import RelativeLayout

from kivy.garden.graph import Graph, MeshLinePlot


class Plot(RelativeLayout):
    def __init__(self, **kwargs):
        super(Plot, self).__init__(**kwargs)
        self.graph = Graph(xlabel="x", ylabel="y", x_ticks_minor=5, x_ticks_major=25, y_ticks_major=1,
                           y_grid_label=True, x_grid_label=True, x_grid=True, y_grid=True,
                           xmin=-0, xmax=100, ymin=-1, ymax=1, draw_border=False)
        # graph.size = (1200, 400)
        # self.graph.pos = self.center

        self.plot = MeshLinePlot(color=[1, 1, 1, 1])
        self.plot.points = [(x, sin(x / 10.)) for x in range(0, 101)]
        self.plot2 = MeshLinePlot(color=[1, 0, 0, 1])
        self.plot2.points = [(x, cos(x / 10.)) for x in range(0, 101)]
        self.add_widget(self.graph)

        self.graph.add_plot(self.plot)
        self.graph.add_plot(self.plot2)


class GraphLayoutApp(App):

    def build(self):
        scroll_view = ScrollView()
        grid_layout = GridLayout(cols=1, padding=20, spacing=20, size_hint_y=None)
        grid_layout.bind(minimum_size=grid_layout.setter('size'))
        graph = Plot(size_hint_y=None, height=500)
        graph2 = Plot(size_hint_y=None, height=500)
        label = Label(text="Hello World!", size_hint_y=None)
        label2 = Label(text="Hello World!", size_hint_y=None)
        grid_layout.add_widget(label)
        grid_layout.add_widget(graph)
        grid_layout.add_widget(label2)
        grid_layout.add_widget(graph2)
        scroll_view.add_widget(grid_layout)

        # return grid_layout
        return scroll_view


if __name__ == '__main__':
    GraphLayoutApp().run()

这篇关于带有MeshLinePlot混淆的Python Kivy图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆