Pass data between two screens or reach app from within python class with kivy

16 views Asked by At

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!

0

There are 0 answers