Kivy:在我的应用中添加工具栏

时间:2014-08-27 21:47:45

标签: android python python-2.7 drawing kivy

我正在尝试实现一个简单的工具栏。现在我被困在了基础上。

我目前的目标:

位于应用侧面的工具栏,允许用户将小部件添加到主gui。

我目前的进展:

位于正确位置的白色矩形。添加正确小部件的按钮。我需要正确定位按钮。

理想情况下,我想使用某种布局(Box?)。但是我无法弄清楚如何将它嵌入矩形中。

我也不知道为什么到目前为止我所做的不起作用。

当前代码:

我会附上一段代码,但按钮位置不正确。如果这更有帮助,我会很乐意提供最少的代码(只要问:))。

Python代码:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import Property, NumericProperty, ReferenceListProperty,\
    ObjectProperty
from kivy.graphics import Color, Ellipse, Line
from kivy.clock import Clock
import math

class GraphToolBar(Widget):

    def add_buttons(self, game):
        createNodeButton = Button(text = 'CreateNode', pos = (self.x,game.height))
        createEdgeButton = Button(text = 'CreateEdge', pos = (self.x,0.8*game.height))

        self.add_widget(createNodeButton)
        self.add_widget(createEdgeButton)

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

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

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



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

    def update(self, dt):
        for widget in self.children:
            if isinstance(widget, GraphEdge) and widget.collide_widget(self):
                widget.check_connection()

    def construct_toolbar(self):
        self.toolbar.add_buttons(self)

class GraphNode(Widget):
    r = NumericProperty(1.0)

    def __init__(self, **kwargs):
        self.size= [50,50]
        self.pos = [175,125]
        self.r = 1.0
        super(GraphNode, self).__init__(**kwargs)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            if touch.grab_current == None:
                self.r = 0.6
                touch.grab(self)             
                return True                
        return super(GraphNode, self).on_touch_down(touch)

    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):
                widget.snap_to_node(self)


    def on_touch_up(self, touch):
        if touch.grab_current is self:
            touch.ungrab(self)
            self.r = 1.0
            # and finish up here

    pass

class GraphEdge(Widget):
    r = NumericProperty(1.0)
    connected_point_0 = Property(False)
    connected_point_1 = Property(False)
    connected_node_0 = Widget()
    connected_node_1 = Widget()

    def __init__(self, **kwargs):
        super(GraphEdge, self).__init__(**kwargs)
        with self.canvas:
            Color(self.r, 1, 1, 1)
            self.line = Line(points=[100, 200, 200, 200], width = 2.0, close = True)
            self.center = ((self.line.points[0]+self.line.points[2])/2,(self.line.points[1]+self.line.points[3])/2)


    def snap_to_node(self, node):
        if self.collide_widget(node):
            distance_from_0 = [math.sqrt(((self.line.points[0]-node.center[0])**2 + (self.line.points[1]-node.center[1])**2))]*2
            distance_from_1 = [math.sqrt(((self.line.points[2]-node.center[0])**2 + (self.line.points[3]-node.center[1])**2))]*2

            if distance_from_0 < distance_from_1:
                if (self.connected_point_0 is False):
                    print "collision"                
                    if node is not self.connected_node_1:
                        self.connected_point_0 = True
                        self.connected_node_0 = node
                        self.line.points = node.center + self.line.points[2:]
                        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)
                return True

            elif distance_from_1 < distance_from_0:
                if (self.connected_point_1 is False):
                    print "collision"
                    if node is not self.connected_node_0:
                        self.connected_point_1 = True
                        self.connected_node_1 = node
                        self.line.points =  self.line.points[:-2] + 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)
                    return True
        pass

    def check_connection(self):
        if self.connected_point_0:
            self.line.points = self.connected_node_0.center + self.line.points[2:] 
            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)
            self.r = self.connected_node_1.r

        if self.connected_point_1:
            self.line.points = self.line.points[:2] + self.connected_node_1.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)
            self.r = self.connected_node_1.r

class GraphApp(App):

    def build(self):
        game = GraphInterface()

        game.construct_toolbar()

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

if __name__ == '__main__':

    GraphApp().run()

.kv文件:

#:kivy 1.0.9

<GraphInterface>:
    node: graph_node
    toolbar: graph_toolbar

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

    GraphToolBar:
        id: graph_toolbar
        size: root.width * 2/10, root.height
        x: root.width * 8/10
        y: 0

<GraphToolBar>:
    size: 10,100

    canvas:
        Color:
            rgba: (1,1,1,1)
        Rectangle:
            size: self.size
            pos: self.pos

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


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

感谢您的耐心等待!

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你只想将这些按钮放到白色矩形上。正如您所提到的,使用BoxLayout可以轻松完成。只需更改此行

即可
class GraphToolBar(Widget):

到这一行

class GraphToolBar(BoxLayout):