【问题标题】:Kivy: Adding a toolbar to my appKivy:向我的应用程序添加工具栏
【发布时间】:2014-08-27 21:47:44
【问题描述】:

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

我目前的目标:

位于应用侧面的工具栏,允许用户将小部件添加到主 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

感谢您的耐心等待!

【问题讨论】:

    标签: android python python-2.7 drawing kivy


    【解决方案1】:

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

    class GraphToolBar(Widget):
    

    到这一行

    class GraphToolBar(BoxLayout):
    

    【讨论】:

    • 没想到会这么简单!但是,如果我不想用按钮完全填充布局空间怎么办? (现在按钮真的很大)。我会给你答案,因为你确实解决了我的问题:)
    • 创建这些按钮时,可以使用size_hint 设置相对大小,或者如果将其设置为(None, None),则可以使用size,设置绝对大小。跨度>
    猜你喜欢
    • 1970-01-01
    • 2013-09-29
    • 2016-12-13
    • 1970-01-01
    • 2017-10-27
    • 2015-07-16
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多