2014-08-27 5 views
0

Я пытаюсь реализовать простую панель инструментов. Прямо сейчас я застрял на основах.Kivy: добавление панели инструментов в мое приложение

Моя цель:

панель инструментов, которая сидит на стороне приложения, а также позволяет пользователю добавлять виджеты в основной графический интерфейс.

Мой текущий прогресс:

белый прямоугольник, который находится в правильном месте. Кнопки, которые добавляют правильные виджеты. Мне нужно правильно расположить кнопки.

Похоже, что я хотел бы использовать какой-то макет (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

Если вы правильно поняли, вы просто хотите, чтобы эти кнопки были на белом прямоугольнике. Это можно легко сделать, используя BoxLayout, как вы уже упоминали. Просто измените эту строку

class GraphToolBar(Widget): 

этой линии

class GraphToolBar(BoxLayout): 
+0

Я не понимал, что это будет так просто! Однако, что, если я не хочу полностью заполнять пространство макета кнопками? (Как сейчас, кнопки действительно большие). Я дам вам ответ, так как вы действительно решили проблему. :) – user124784

+1

Когда вы создаете эти кнопки, вы можете использовать 'size_hint' для установки относительного размера или если вы установите его на' (None, None) ', вы можете затем используйте 'size', который устанавливает абсолютный размер. – Tatarkow

Смежные вопросы