【问题标题】:Kivy custom widget to plot data, can't get current widget dimensionsKivy 自定义小部件绘制数据,无法获取当前小部件尺寸
【发布时间】:2021-09-05 20:58:31
【问题描述】:

我想创建一个自定义 kivy 小部件,该小部件绘制数据以响应用户输入或实时位置数据。 我需要小部件的当前尺寸和位置来绘制线条,但我似乎无法正确获取它们,并且我也无法通过单击按钮来触发线条更新。

这是一个示例代码,当单击按钮时,GraphWidget 应该绘制线条。

import numpy as np
from kivy.app import App
from kivy.properties import ObjectProperty, NumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget

class BoxLayoutMain(BoxLayout):

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

        self.gw = GraphWidget()

    def plot_line(self):
        # called when user clicks button
        data = np.asarray([[0,0],[100,100],[200,50]]) # test data
        self.gw.plot(data, min_x=0, max_x=200, min_y=0, max_y=150)

class GraphWidget(Widget):

    trace_points = ObjectProperty((0, 0, 0, 0))

    graph_w = NumericProperty(100)
    graph_h = NumericProperty(100)
    graph_x0 = NumericProperty(0)
    graph_y0 = NumericProperty(0)

    def on_size(self, *args):
        # dimensions are correct here:
        self.graph_w = self.width
        self.graph_h = self.height
        self.graph_x0 = self.pos[0]
        self.graph_y0 = self.pos[1]

        self.test()

    def test(self):

        # dimensions are also correct here:
        print('W ', self.graph_w)
        print('H ', self.graph_h)
        print('X ', self.graph_x0)
        print('Y ', self.graph_y0)

        # a test line is drawn when triggered by on_size method
        self.trace_points = [400, 0, 600, 500]

    def plot(self,data_xy, min_x, max_x, min_y, max_y):

        # called when user clicks button
        # dimensions are not correct here:
        print('W ', self.graph_w)
        print('H ', self.graph_h)
        print('X ', self.graph_x0)
        print('Y ', self.graph_y0)

        # transforming data points to pixels, needs correct widget dimensions/position:

        xf = self.graph_w / (max_x - min_x)
        yf = self.graph_h / (max_y - min_y)

        X = (data_xy[:, 0] - min_x) * xf  + self.graph_x0
        Y = (data_xy[:, 1] - min_y) * yf  + self.graph_y0

        nps = np.column_stack((X, Y))

        # line is not drawn/updated
        self.trace_points = list(nps.flatten().astype(int))


class GraphTestApp(App):
    pass

GraphTestApp().run()

kv 文件:

BoxLayoutMain:

<BoxLayoutMain>:
    orientation: 'horizontal'

    Button:
        text: 'Click'
        on_press: root.plot_line()

    GraphWidget:

<GraphWidget>:

    canvas:
        Color:
            rgb: 1,0,0
        Line:
            width: 2
            points: self.trace_points

谢谢!

【问题讨论】:

    标签: python graph kivy widget dimension


    【解决方案1】:

    问题在于:

    self.gw = GraphWidget()
    

    BoxLayoutMain__init__() 方法中创建GraphWidget 的新实例,而该实例不在您的GUI 中。因此,任何对self.gw 的引用都与您的GUI 中的GraphWidget 无关。您只需要获得对GraphWidget 正确实例的引用。一种方法是使用ObjectPropertyids。您可以修改您的BoxLayoutMain 以拥有一个名为gwObjectProperty

    class BoxLayoutMain(BoxLayout):
        gw = ObjectProperty(None)
    
        # def __init__(self, **kwargs):
        #     super().__init__(**kwargs)
        #     self.gw = GraphWidget()
    

    并且不再需要__init__() 方法。然后将ids 添加到您的kv

    BoxLayoutMain:
    
    <BoxLayoutMain>:
        gw: gw  # set the gw ObjectProperty to the widget with id of gw
        orientation: 'horizontal'
    
        Button:
            text: 'Click'
            on_press: root.plot_line()
    
        GraphWidget:
            id: gw  # id used above to get a reference to this GraphWidget
    
    <GraphWidget>:
    
        canvas:
            Color:
                rgb: 1,0,0
            Line:
                width: 2
                points: self.trace_points
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 2015-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多