I have a screen that creates some widgets depending on how many entries there are in a database. Essentially, for each entry in the database there is a little grid added to the screen containing some of the information. Within my Main(MDApp) class, I load in the data and add a TourGrid widget (written python class inheriting from GridLayout) to the screen containing some of the information from the data. What I want is to be able to click on these grids and then navigate to a new page that then allows you to do other things, but working within the framework of this specific entry in the database. The TourGrid is clickable, because it also inherits from ButtonBehavior, and I can save the id of the database entry in the class which can then be called upon in the on_press method. However, I don't know how to switch to another screen from within this grid, and also to pass the data along with it. I can't reach app or call root from within this structure, and though I can call self.parent.parent.parent.parent.manager to get to the screen manager that doesn't seem like the right solution. Ideally I could call it from within the Main class so that I don't have to redo the firebase credentials and initialization many times over. How can I achieve 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
from kivymd.uix.pickers import MDDatePicker
from kivymd.uix.menu import MDDropdownMenu
from datetime import datetime, date
import firebase_admin
from firebase_admin import db, credentials
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)
print(Window.size)
return Builder.load_file("main.kv")
def on_start(self):
# Get database data
self.tour_data = {'-abcde': {'acc_id': 0, 'date_tour_created': '28-02-2024', 'ending_date': '', 'name': 'Tour', 'privacy': 'My friends', 'starting_date': '28-02-2024'}
self.populate_my_tours()
def populate_my_tours(self):
# Populate tour grid on home screen
tours_grid = self.root.ids["my_tours"].ids["tours_grid"]
for tour_id, tour in self.tour_data.items():
tours_grid.add_widget(TourGrid(tour_name=tour["name"], starting_date=tour["starting_date"], tour_id=tour_id))
if __name__ == "__main__":
Main().run()
main.kv
#:include kv/my_tours.kv
BoxLayout:
ScreenManager:
id: screen_manager
MyToursScreen:
id: my_tours
name: "my_tours"
tour_grid.py
from kivy.uix.gridlayout import GridLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.label import Label
from kivy.uix.behaviors import ButtonBehavior
from kivy.graphics import Color, RoundedRectangle
from kivy.metrics import dp
import kivy.utils
class TourGrid(ButtonBehavior, GridLayout):
def __init__(self, **kwargs):
super(TourGrid, self).__init__()
self.tour_id = kwargs["tour_id"]
self.cols = 1
with self.canvas.before:
Color(rgb=kivy.utils.get_color_from_hex("#dddddd"))
self.rect = RoundedRectangle(size=self.size, pos=self.pos, radius=[(10, 10), (10, 10), (10, 10), (10, 10)])
self.bind(pos=self.update_pos_size, size=self.update_pos_size)
# Top layout containing name of tour
top = AnchorLayout(anchor_x="left", anchor_y="top")
tour_name_label = Label(text=str(kwargs["tour_name"]), size_hint=[None, None], padding=[dp(8), dp(6)], color=kivy.utils.get_color_from_hex("#000000"), font_name="Proxima Nova")
tour_name_label.texture_update()
tour_name_label.size = tour_name_label.texture_size
top.add_widget(tour_name_label)
# Bottom layout containing starting date
bottom = AnchorLayout(anchor_x="left", anchor_y="bottom")
starting_date_label = Label(text=str(kwargs["starting_date"]), size_hint=[None, None], padding=[dp(8), dp(6)], color=kivy.utils.get_color_from_hex("#000000"), font_name="Proxima Nova")
starting_date_label.texture_update()
starting_date_label.size = starting_date_label.texture_size
bottom.add_widget(starting_date_label)
self.add_widget(top)
self.add_widget(bottom)
def on_press(self):
print(self.parent.parent.parent.parent.manager)
print(self.tour_id)
def update_pos_size(self, *_):
self.rect.pos = self.pos
self.rect.size = self.size
my_tours.kv
#:import utils kivy.utils
<MyToursScreen@Screen>:
FloatLayout:
# Top bar, profile image and name, notification and settings button
GridLayout:
rows: 1
size_hint: 1, 0.075
pos_hint: {"top": 1, "left": 1}
canvas:
Color:
rgb: utils.get_color_from_hex("#2e6407")
Rectangle:
size: self.size
pos: self.pos
Image:
id: account_image
# Main grid with tours
ScrollView:
size_hint: 0.8, 0.825
pos_hint: {"top": 0.925, "right": 0.9}
GridLayout:
id: tours_grid
cols: 1
size_hint_y: None
height: self.minimum_height
row_default_height: "80dp"
row_force_default: True
spacing: 0, dp(8)
Label:
text: "Planned trips"
color: utils.get_color_from_hex("#000000")
font_size: sp(20)
bold: True
# Bottom bar, My Tours, Add Tour and Friends buttons
GridLayout:
rows: 1
size_hint: 1, 0.1
canvas:
Color:
rgb: utils.get_color_from_hex("#2e6407")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "My tours"
bold: True
MDIconButton:
icon_size: dp(50)
icon: "plus"
Button:
text: "Friends"
background_normal: ""
background_color: utils.get_color_from_hex("#2e6407")
I tried to filter out the unnecessary bits, hope there's no problems!