2014-11-21 68 views
0

我是一個新的程序員(和第一次stackoverflow海報)所以請糾正我,如果我不正確地使用術語或使任何其他的錯誤禮儀或適當的編碼樣式。Kivy佈局定位問題 - 不理解/正確使用__init__,kv,kv屬性

我想寫一個遊戲,你畫瓷磚到你的瓷磚架,然後在電路板上播放它們。我已經編寫了一個無需通過文本輸入就可以工作的遊戲。現在我想用Kivy來製作一個圖形界面。

我的一個問題涉及小部件的定位。我想將我的機架小部件放在屏幕x軸的中心。我可以讓它在那裏繪製一個矩形,讓它看起來被定位在我想要的位置,但是它的x位置(正如您可能猜到的)0.我認爲我的部分問題是我已經將一個Game對象傳遞給了我的小部件並使用符號列表(game.symbols)和一個方法,我嘗試加載帶有標籤(文本=符號)的創建瓦片小部件,然後將它們加載到機架上。正如你可能已經猜到的,我的瓷磚也沒有正確定位。

  1. 如何正確放置我的瓷磚機架並正確加載我的瓷磚,以便它們具有正確的位置(我認爲這對我的碰撞檢測是必需的)。
  2. 請解釋方法init方法和KV文件在使用時都會執行。
  3. 什麼是正確的方式來傳遞對象和屬性的小部件關於我的問題在這裏。我應該創建一個ObjectProperty嗎?

我也可能對Kivy的定位和佈局有一個基本的誤解,如果是的話,請教育我。

謝謝 崖

import kivy 
kivy.require('1.7.0') 
from kivy.app import App 
from kivy.lang import Builder 
from kivy.uix.floatlayout import FloatLayout 
from kivy.uix.scatter import Scatter 
from kivy.uix.label import Label 

kv_Game= ''' 
<TileWidget>: 
    size_hint: None, None 
    size: 50,50 
    canvas.before: 
     Color: 
      rgba: 0.5,0.5,1,0.3 
     Rectangle: 
      size: self.width, self.height 

    canvas.after: 
     Line: 
      rectangle: self.x, self.y, self.width, self.height 
      dash_offset: 5 
      dash_length: 3 

<RackWidget>: 

    size_hint: None, None 
    size: 350, 50 
    pos_hint: {'center_x': 0.5} 
    y: 75 

    canvas.after: 
     Color: 
      rgba: 1,0,0,0.5 
     Line: 
      rectangle: self.x, self.y, self.width, self.height 
''' 

Builder.load_string(kv_Game) 

class Game(FloatLayout): 

    def __init__(self, **kwargs): 
     super(Game, self).__init__(**kwargs) 
     self.symbols = ['!','@','#','$','%','^','&'] 
     self.rackWidget = RackWidget(self) 
     self.add_widget(self.rackWidget) 

class TileWidget(Scatter): 

    def __init__(self, symbol="?", **kwargs): 
     super(TileWidget, self).__init__(**kwargs) 
     tileLabel = Label(text=symbol, size_hint=(None,None), size=(50,50)) 
     self.add_widget(tileLabel) 

class RackWidget(FloatLayout): 

    def __init__(self, game, **kwargs): 
     super(RackWidget, self).__init__(**kwargs) 
     print("TileRackWidget pos:", self.pos) 

     x, y = self.pos 
     for symbol in game.symbols: 
      tileWidget = TileWidget(symbol=symbol, pos= (x,y)) 
      self.add_widget(tileWidget) 
      print("tileWidget pos:", tileWidget.pos) 
      x+=50 

class GameTest1App(App): 
    def build(self): 

     game = Game() 
     return game 

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

回答

0

pos當您創建RackWidget實例未設置爲可使用的值呢。當__init__正在運行時,該小部件尚未添加到Game小部件中,因此它沒有父級,也沒有定位信息。您可以通過綁定到RackWidget.pos中的更改來解決此問題,但有一種更簡單的方法可以執行此操作:RelativeLayoutRelativeLayout的每個孩子的位置將基於佈局本身的位置。

這是一個使用RelativeLayoutRackWidget修改後的版本:

class RackWidget(RelativeLayout): 

    def __init__(self, game, **kwargs): 
     super(RackWidget, self).__init__(**kwargs) 
     print("TileRackWidget pos:", self.pos) 

     x, y = 0, 0 
     for symbol in game.symbols: 
      tileWidget = TileWidget(symbol=symbol, pos= (x,y)) 
      self.add_widget(tileWidget) 
      print("tileWidget pos:", tileWidget.pos) 
      x+=50 
+0

謝謝! 肯定會更好。但是,打印的位置現在與RelativeLayout相關聯,包括TileRackWidget的位置。我可以理解瓷磚是相對於其父母,但機架也相對於它自己嗎?: TileRackWidget pos:[0,75] tileWidget pos:(0.0,0.0) tileWidget pos:(50.0,0.0) tileWidget POS(100.0,0.0) tileWidget POS(150.0,0.0) tileWidget POS(200.0,0.0) tileWidget POS(250.0,0.0) tileWidget POS(300.0,0.0) 這給了我當我使用collide_widget時出現問題。也許你提出的約束是要走的路? – cdub 2014-11-21 21:45:41

+0

噢,這是我想的問題。如果你有一點時間,我會對如何在init內進行綁定的問題感興趣。 – cdub 2014-11-21 21:57:38

+0

您可以使用'Widget.to_window(* pos)'獲取基於Widget的相對於窗口的座標。 – 2014-11-24 15:46:34