2016-04-02 47 views
3

我有幾個小部件,並希望「拖動和選擇」它們。我使用選擇小部件作爲矩形來顯示選擇大小,然後使用for child in root.children: selection.collide_widget(child)。這個效果很好,只要我從左下角拖到右上角,因爲選擇小部件的大小將是正面的。collide_widget負尺寸

預計負尺寸的小部件將無法與collide_widget一起使用嗎?

我不應該使用小部件的負尺寸嗎?

KV文件:

<SelectionBox>: 
    size: 0,0 
    size_hint: None, None 
    canvas: 
     Color: 
      rgba: 1, 1, 1, 0.1 
     Rectangle: 
      pos: root.pos 
      size: root.size 

<Selectable>: 
    size: 32, 32 
    size_hint: None, None 
    canvas: 
     Color: 
      rgba: 0, 1, 0, 1 
     Rectangle: 
      pos: root.pos 
      size: root.size 

代碼:

class Selectable(Widget): 
    pass 

class Canvas(FloatLayout): 

    touch_down = False 

    def on_touch_down(self, touch): 
     self.selection = sel = SelectionBox() 
     sel.pos = touch.pos 
    self.touch_down = True 
     self.add_widget(sel) 

    def on_touch_move(self, touch): 
     if self.touch_down: 
#~~~~~~~~~~~~~~~~~~~~~~~~~ Interesting line here ~~~~~~~~~~~~~~~~~~~~~~~~~ 
      # size can get negative 
      self.selection.size = (touch.pos[0] - self.selection.pos[0] , touch.pos[1] - self.selection.pos[1]) 

    def on_touch_up(self, touch): 

     for widget in self.children: 
      if widget is self.selection: 
       print("Children is selection") 
      if self.selection.collide_widget(widget): 
      print("Widget collides: {}".format(widget)) 

     self.touch_down = False 
     self.remove_widget(self.selection) 

canvas = Canvas() 

class MyApp(App): 
    def build(self): 
     canvas = Canvas() 
    for i in range(0,11): 
     sel = Selectable() 
     sel.pos = random.random() * 1000, random.random() * 1000 
     self.add_widget(sel) 
     return canvas 

if __name__ == "__main__": 
    MyApp().run() 

回答

1

事實上,這是正常現象。從kivy.uix.widget.Widget

def collide_widget(self, wid): 
    if self.right < wid.x: 
     return False 
    if self.x > wid.right: 
     return False 
    if self.top < wid.y: 
     return False 
    if self.y > wid.top: 
     return False 
    return True 

對於負大小,此邏輯將行不通,因爲例如self.right < self.x。一個簡單的解決辦法是重新定義collide_widget這些類的其中負尺寸預期:

def collide_widget(self, wid):  
    if max(self.x, self.right) < min(wid.x, wid.right): 
     return False 
    if min(self.x, self.right) > max(wid.x, wid.right): 
     return False 
    if max(self.top, self.y) < min(wid.y, wid.top): 
     return False 
    if min(self.top, self.y) > max(wid.y, wid.top): 
     return False 
    return True 

這需要同時兼顧小窗口的具有正或負的大小(所述一個主叫collide_widget和所述一個被測試)。

但是,我不確定,如果其他地方的代碼依賴於負值不會像預期的那樣發生碰撞(所以請小心地將其貼到Widget上)。