Kivy:了解应用程序中的小部件实例 [英] Kivy: understanding widget instances in apps
问题描述
我仍在为Kivy做准备,希望您不要介意我的另一个问题!
I'm still warming up to this Kivy stuff, hope you don't mind another question from me!
我试图了解我的一些小部件的预定事件.出于上下文考虑,我希望能够将节点移动到边缘,并使边缘捕捉"到该节点.
I'm trying to understand scheduled events for some of my widgets. For the sake of context, I want to be able to move nodes onto edges, and have the edges 'snap to' the node.
这是我的.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代码:
I have a collision detection event between nodes and edges, and I am dynamically creating nodes and edges within my program. Here is the relevant python code:
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
好,所以要阅读很多(对不起)!
Ok, so that's a lot to read (sorry)!
基本上,仅针对在.kv文件中创建的初始边缘和节点检测到我的碰撞.新创建的边缘和节点无法通过碰撞机制进行交互.
Basically my collision is only detected for the initial edges and nodes I create in the .kv file. The newly created edges and nodes cannot interact via the collision mechanism.
如果人们愿意,我可以提供更多代码,但我认为这应该是所有相关的部分.谢谢!
I can put up more code if people want but I think that should be all the relevant parts. Thanks!
新方法:
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)
使用此代码,我仍然可以通过快速移动节点来断开连接.
With this code I can still break the connection by moving the nodes quickly.
我也许还为时过早.我只能与产生的第一个边缘互动.而且我还有一个怪异的错误,其中第一个边缘和第一个节点似乎具有相同的颜色属性.尽管也许应该在它自己的问题中提出这个问题.
I perhaps gave the answer a little prematurely. I can only interact with the first edge I spawned. And I also have a weird bug where the first edge and the first node seem to have the same color properties. Though perhaps this should be posed in it's own question.
推荐答案
问题是您不会对添加到GraphInterface
的新GraphEdge
或GraphNode
做出反应.在update
:
The problem is that you don't react to new GraphEdge
s or GraphNode
s being added to your GraphInterface
. In update
:
self.edge.snap_to_node(self.node)
self.edge
始终是kv创建的GraphEdge
.与self.node
相同.
self.edge
is always the kv-created GraphEdge
. Same with self.node
.
您应该尝试在触摸交互中将此交互添加到GraphNode
类本身中.在GraphNode.on_touch_move()
中尝试这样的事情:
You should try adding this interaction to the GraphNode
class itself, in your touch interactions. Try something like this in 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
.
This way, each GraphNode
searches through its siblings for any GraphEdge
with which it may collide.
这篇关于Kivy:了解应用程序中的小部件实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!