I'm creating labels based on information that I'm drawing from a database, and I would like to left align it in the grid. For this, I'm trying to wrap the label tightly around the text so I can left align the label in an AnchorLayout. Because the text in my label and the number of these grids with labels are dynamic, I'm doing this through python rather than in a kv file. I've seen a ton of documentation on how to do this in the kivy language, but I can't figure it out in python. Just calling tour_name_label.texture_size (see below) returns [0. 0], I can't seem to access this property and set it to the label size. I'm new to kivy, so I'm not super comfortable with the bind and getters/setters methods. How should I tackle this?
main.py
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from tour_grid import TourGrid
from kivy.core.window import Window
from kivy.core.text import LabelBase
import requests
import json
class MyToursScreen(Screen):
pass
class Main(MDApp):
acc_id = 0
def build(self):
# self.theme_cls.material_style = "M3"
# self.theme_cls.theme_style = "Dark"
Window.size = (360, 600)
return Builder.load_file("main.kv")
def on_start(self):
# Sample tour data
tour_data = [{'acc_id': 0, 'date_tour_created': '16-02-2024', 'name': 'Bike Tour Norway', 'starting_date': '13-06-2024', 'tour_id': 0}]
# print(self.root.ids)
# Populate tour grid on home screen
tours_grid = self.root.ids["my_tours"].ids["tours_grid"]
for tour in tour_data:
T = TourGrid(tour_name=tour["name"], starting_date=tour["starting_date"])
tours_grid.add_widget(T)
if __name__ == "__main__":
Main().run()
tour_grid.py (where the problem is)
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.graphics import Color, Rectangle
import kivy.utils
class TourGrid(GridLayout):
def __init__(self, **kwargs):
self.cols = 1
super(TourGrid, self).__init__() # Initialize GridLayout with kwargs
with self.canvas.before:
Color(rgb=kivy.utils.get_color_from_hex("#dddddd"))
self.rect = Rectangle(size=self.size, pos=self.pos)
self.bind(pos=self.update_rect, size=self.update_rect)
# PROBLEM HERE, MADE INTO BUTTON TO CHECK DIMENSIONS
# Top FloatLayout containing name of tour
top = AnchorLayout(anchor_x="center", anchor_y="center")
tour_name_label = Button(text=str(kwargs["tour_name"]), color=kivy.utils.get_color_from_hex("#000000"))
# tour_name_label.bind(texture_size=tour_name_label.setter("size"))
# print(tour_name_label.getter("texture_size"))
# print(tour_name_label.setter("texture_size")())
top.add_widget(tour_name_label)
# Bottom FloatLayout containing starting date
bottom = AnchorLayout(anchor_y="center")
starting_date_label = Label(text="[color=000000]" + kwargs["starting_date"] + "[/color]", size_hint=[1, 0.3], pos_hint={"top": 1, "left": 1}, markup=True)
bottom.add_widget(starting_date_label)
self.add_widget(top)
self.add_widget(bottom)
def update_rect(self, *_):
self.rect.pos = self.pos
self.rect.size = self.size
main.kv
#:include kv/my_tours.kv
BoxLayout:
ScreenManager:
id: screen_manager
MyToursScreen:
id: my_tours
name: "my_tours"
my_tours.kv
#:import utils kivy.utils
<MyToursScreen@Screen>:
FloatLayout:
# Top bar, profile image and name, notification and settings button
GridLayout:
rows: 1
pos_hint: {"top": 1, "left": 1}
size_hint: 1, 0.1
canvas:
Color:
rgb: utils.get_color_from_hex("#25be55")
Rectangle:
size: self.size
pos: self.pos
# Main grid with tours
ScrollView:
pos_hint: {"top": 0.9, "left": 1}
size_hint: 1, 0.8
GridLayout:
id: tours_grid
cols: 1
size_hint_y: None
height: self.minimum_height
row_default_height: "70dp"
row_force_default: True
Label:
text: "Planned trips"
color: utils.get_color_from_hex("#000000")
# Bottom bar, My Tours button
GridLayout:
rows: 1
pos_hint: {"top": 0.1, "left": 1}
size_hint: 1, 0.1
canvas:
Color:
rgb: utils.get_color_from_hex("#25be55")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "My tours"
bold: True
Okay, I found a little (unintuitive) gem in the label docs. I needed to run tour_name_label.texture_update()
before setting tour_name_label.size = tour_name_label.texture_size
. Now it works! Thanks @John Andeson for the size_hint
clue, I also needed that.
https://kivy.org/doc/stable/api-kivy.uix.label.html#kivy.uix.label.Label.anchors