Reputation: 357
I've got the following code snippet that will draw a board. I've read about RelativeLayout
and seen tutorials for manipulating the .kv file, but no explanation on how to relativize the coordinates to the widget with just Python code.
from kivy.uix.widget import Widget
from kivy import graphics
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.app import App
class Chessboard(Widget):
def __init__(self, **kwargs):
super(Chessboard, self).__init__(**kwargs)
self.bind(pos=self.drawBoardandPieces)
self.bind(size=self.drawBoardandPieces)
self.drawBoardandPieces()
def drawBoardandPieces(self, *args):
with self.canvas:
# Reset the canvas in case of redraws.
self.canvas.clear()
# Define the lengths of the edges of the squares.
edge_len = min(self.height, self.width) // 8
for column in range(0, 8):
for row in range(0, 8):
if ((row + column) % 2) == 0:
graphics.Color(0, 0, 1)
self.dark_rect = graphics.Rectangle(pos=(column*edge_len, row*edge_len), size=(edge_len, edge_len))
else:
graphics.Color(1, 1, 1)
self.light_rect = graphics.Rectangle(pos=(column*edge_len, row*edge_len), size=(edge_len, edge_len))
def on_touch_down(self, touch):
print(touch.pos)
class SCApp(App):
def build(self):
app_layout = BoxLayout(orientation="vertical")
app_layout.add_widget(widget=Chessboard())
play_again_btn = Button(text="Play Again", size_hint=(1, 1))
app_layout.add_widget(widget=play_again_btn)
return app_layout
SCApp().run()
Instead of what this code renders, I need the board drawn on the canvas to appear above the button in its own BoxLayout
container.
Also, will click event need to be contained in the RelativeLayout
container, as well, to work only in the context of the board?
Upvotes: 0
Views: 165
Reputation: 357
I solved it. Here's the corrected code in the app. All you need to do is to place the widget into its own RelativeLayout
. Then, the RelativeLayout
widget can, itself, be placed inside of a box in BoxLayout
, a grid position in GridLayout
, etc.
from kivy.uix.relativelayout import RelativeLayout
# All of that other code.
class SCApp(App):
def build(self):
app_layout = BoxLayout(orientation="vertical")
chessboard_layout = RelativeLayout()
chessboard_layout.add_widget(widget=Chessboard())
app_layout.add_widget(widget=chessboard_layout))
play_again_btn = Button(text="Play Again", size_hint=(1, 1))
app_layout.add_widget(widget=play_again_btn)
return app_layout
Upvotes: 0
Reputation: 38937
Note that the documentation specifies:
Kivy drawing instructions are not automatically relative to the widgets position or size.
So you must also handle the position of your chessboard. You can handle the position using something like:
def drawBoardandPieces(self, *args):
with self.canvas:
# Reset the canvas in case of redraws.
self.canvas.clear()
# Define the lengths of the edges of the squares.
edge_len = min(self.height, self.width) // 8
for column in range(0, 8):
for row in range(0, 8):
if ((row + column) % 2) == 0:
graphics.Color(0, 0, 1)
self.dark_rect = graphics.Rectangle(pos=(self.width/2 - 4*edge_len + column*edge_len, self.y + row*edge_len), size=(edge_len, edge_len))
else:
graphics.Color(1, 1, 1)
self.light_rect = graphics.Rectangle(pos=(self.width/2 - 4*edge_len + column*edge_len, self.y + row*edge_len), size=(edge_len, edge_len))
This uses self.y
as the bottom of the chess board and calculates the x
based on the width
of the Widget
and the edge_len
. Probably should also add self.x
to the x
position, but that is zero in your case.
In general, your on_touch_down()
method should check if the touch is on your Widget
as stated in the documentation. If you determine that no other Widgets
need to know about that touch
, your on_touch_down()
method can return True
, otherwise it should return False
.
Upvotes: 1