Kivy布局定位问题 - 不理解/正确使用__init__,kv,kv属性

问题描述:

我是一个新的程序员(和第一次*海报)所以请纠正我,如果我不正确地使用术语或使任何其他的错误礼仪或适当的编码样式。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() 

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