【问题标题】:Kivy: understanding widget instances in appsKivy:了解应用程序中的小部件实例
【发布时间】:2014-08-14 21:06:32
【问题描述】:

我还在为这些 Kivy 的东西热身,希望你不要介意我的另一个问题!

我正在尝试了解我的一些小部件的预定事件。为了上下文,我希望能够将节点移动到边上,并让边“捕捉”到节点。

这是我的 .kv 文件:

<GraphInterface>:
    node: graph_node
    edge: graph_edge

    GraphNode:
        id: graph_node
        center: self.parent.center

    GraphEdge:
        id: graph_edge
        center: 200,200

<GraphNode>:
    size: 50, 50
    canvas:
        Color:
        rgba: (root.r,1,1,1)
    Ellipse:
        pos: self.pos
        size: self.size


<GraphEdge>:
    size: self.size
    canvas:
        Color:
            rgba: (root.r,1,1,1)
        Line:
            width: 2.0
            close: True

我在节点和边之间有一个碰撞检测事件,我正在我的程序中动态创建节点和边。这是相关的python代码:

class GraphInterface(Widget):
    node = ObjectProperty(None)
    edge = ObjectProperty(None)

    def update(self, dt):
        # detect node collision
        self.edge.snap_to_node(self.node)
        return True

class GraphEdge(Widget):
    r = NumericProperty(1.0)
    def __init__(self, **kwargs):
        super(GraphEdge, self).__init__(**kwargs)
        with self.canvas:
            self.line = Line(points=[100, 200, 200, 200], width = 2.0, close = True)

    def snap_to_node(self, node):
        if self.collide_widget(node):
            print "collision detected"
            del self.line.points[-2:]
            self.line.points+=node.center
            self.size = [math.sqrt(((self.line.points[0]-self.line.points[2])**2 + (self.line.points[1]-self.line.points[3])**2))]*2
            self.center = ((self.line.points[0]+self.line.points[2])/2,(self.line.points[1]+self.line.points[3])/2)
    pass

class GraphApp(App):

    def build(self):
        node = GraphNode()
        game = GraphInterface()

        createNodeButton = Button(text = 'CreateNode', pos=(100,0))
        createEdgeButton = Button(text = 'CreateEdge')
        game.add_widget(createNodeButton)
        game.add_widget(createEdgeButton)

        #scatter = Scatter(do_rotation=False, do_scale=False)
        #scatter.add_widget(node)

        def createNode(instance):
            newNode = GraphNode()
            game.add_widget(newNode)
            #scatter.add_widget(newNode)
            print "Node Created"

        def createEdge(instance):
            newEdge = GraphEdge()
            game.add_widget(newEdge)
            #scatter.add_widget(newEdge)
            print "Edge Created"

        createNodeButton.bind(on_press=createNode)
        createEdgeButton.bind(on_press=createEdge)

        Clock.schedule_interval(game.update, 1.0/60.0)   
        return game

好的,有很多东西要读(抱歉)!

基本上,我的碰撞只检测到我在 .kv 文件中创建的初始边和节点。新创建的边和节点不能通过碰撞机制进行交互。

如果人们愿意,我可以提供更多代码,但我认为这应该是所有相关部分。谢谢!

编辑:

新方法:

def on_touch_move(self, touch):
    if touch.grab_current is self:
        self.pos=[touch.x-25,touch.y-25]
    for widget in self.parent.children:
        if isinstance(widget, GraphEdge) and widget.collide_widget(self):
            print "collision detected"
            widget.snap_to_node(self)
            return True
    return super(GraphNode, self).on_touch_move(touch)

使用此代码,我仍然可以通过快速移动节点来断开连接。

EDIT2:

我可能给出的答案有点过早。我只能与我生成的第一条边进行交互。而且我还有一个奇怪的错误,第一条边和第一个节点似乎具有相同的颜色属性。虽然也许这应该在它自己的问题中提出。

【问题讨论】:

    标签: python python-2.7 drawing kivy


    【解决方案1】:

    问题是您对添加到您的GraphInterface 的新GraphEdges 或GraphNodes 没有反应。在update:

        self.edge.snap_to_node(self.node)
    

    self.edge 始终是 kv 创建的 GraphEdge。与self.node 相同。

    您应该尝试在触摸交互中将此交互添加到GraphNode 类本身。在GraphNode.on_touch_move() 中尝试这样的事情:

    for widget in self.parent.children:
        if isinstance(widget, GraphEdge) and widget.collide_widget(self):
            print "collision detected"
            ...
            break
    

    这样,每个GraphNode 都会在其兄弟姐妹中搜索可能与之发生冲突的任何GraphEdge

    【讨论】:

    • 再次感谢瑞恩!但是,我看到了与节点相同的问题。如果我移动得太快,边缘不会捕捉到节点。我尝试使用与以前类似的修复方法,但没有成功。我将上传更新的方法,也许我做了一些明显错误的事情:)。再次感谢!
    • 在您的编辑中,您说“断开连接” - 这是否意味着边缘会折断,但是您可以将节点拉离边缘并且不再折断?如果您希望边缘保持连接,您应该添加特定的功能来做到这一点,并在边缘连接到节点后停止检查碰撞。
    • 你说的是对的。当我试图弄清楚如何做事时,我有点像破解这段代码。我的最终目标是一个交互式图网络,我离那个还很远!我目前不喜欢如何更新节点位置,我会尝试考虑一个新的来做到这一点。我还在最后添加了一些关于一些着色错误的内容,这是我可以轻松修复的吗? (如果它足够重要,我会提出一个新问题)。谢谢。
    • 是的,我不确定。您可能应该为此提出一个新问题,并提供一些额外的细节和代码/kv。
    • 好的,当然。我只是觉得我所做的每一个更改都会引入一堆我无法解决的新问题(或在网上找到解决方案)。我会发布一个关于颜色错误的问题。我仍然有这个问题的问题,即我的节点只与第一个边缘交互。我不知道如何实现你上面描述的功能,但我愿意试一试:)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2018-09-10
    相关资源
    最近更新 更多