Because of your need it appears that you need not only to load the next phase, but also to close/download the previous one, because in case you don’t, it will take up memory in your project, so to solve this as I said in the chat on 29/01:
I understand little of this, but from what I understand it is not enough to "load" with Builder.load_file and "download" with Builder.unload_file and of course, after downloading, run in the "widget" that is loading the widget.clear_widgets()? Of course there can probably be one or the other thing, like "events", but then just plan well the code to remove at the right time
I did not formulate the answer because I had not had time to downgrade Python3.8 to 3.7 (the kivy still does not have support for 3.8), now done the tests I will formalize the answer, in the example self.palco
refers ai Main layout of the application, assuming that the fase1
is already loaded and you want to carry the fase2
should look like this:
# Remove a fase antiga
self.palco.clear_widgets()
# carrega e adiciona a fase2
self.palco.add_widget(Builder.load_file('fases/fase2.kv'))
# DESCARREGA e a fase1 (que já foi removida com o clear_widgets)
Builder.unload_file('fases/fase1.kv')
So basically we had to use:
To test created the following example:
# -*- coding: latin-1 -*-
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.gridlayout import GridLayout
class GameApp(App):
palco = None
fase_atual = 1
total_fases = 3
def run(self):
super().run()
def on_start(self):
self.palco = self.root.ids['palco']
self.palco.add_widget(Builder.load_file(f'fases/fase{self.fase_atual}.kv'))
def alerta(self, texto):
layout = GridLayout(cols=1, padding=10)
popup = Popup(title='Jogo', auto_dismiss=False, content=layout)
label = Label(text=texto)
layout.add_widget(label)
fechar = Button(text="Continuar")
fechar.bind(on_press = popup.dismiss)
layout.add_widget(fechar)
popup.open()
def carregar_fase(self, novo):
print('Removendo fases')
self.palco.clear_widgets()
print(f'Carrengado o fase {novo}')
self.palco.add_widget(Builder.load_file(f'fases/fase{novo}.kv'))
anterior = self.fase_atual
self.fase_atual = novo
print(f'Decarrengado o fase {anterior}')
Builder.unload_file(f'fases/fase{anterior}.kv')
def voltar_fase(self):
proximo = self.fase_atual - 1
if proximo < 1:
self.alerta('Não há fases anteriores')
else:
self.carregar_fase(proximo)
def proxima_fase(self):
proximo = self.fase_atual + 1
if proximo > self.total_fases:
self.alerta('Não há próximas fases')
else:
self.carregar_fase(proximo)
if __name__ == '__main__':
GameApp().run()
And in the game.kv
added:
GridLayout:
cols: 1
BoxLayout:
id: palco
Button:
text: "Fase anterior"
on_release:
app.voltar_fase()
Button:
text: "Próximo fase"
on_release:
app.proxima_fase()
In the example the GridLayout
is the layout of the whole program, buttons and current phase of the game, the "buttons" (Earlier stage and Next map) which are only for testing maps. Already the BoxLayout
should receive the widgets that represent the current phase, it is the "stage".
The alert window, def alerta(self, texto)
, does not influence the functioning, it is merely to understand that there was a problem when trying to access a phase outside the "range" (in the example the range is 3 phases).
An important detail, to use the "native kivy" property called self.root.ids
you need to wait for the screen to load the main components related to the App
, soon the self.root.ids
won’t work if used in the methods:
def __init__
def build
def run
(replacement in inheritance)
That’s why I used the def on_load(self)
, so it is possible to get the ids and in the case of the example the "stage" (BoxLayout
) to receive the phases.
You can add at the end of the answer a small example of how the file would look
.py
and the file.kv
please ?– JeanExtreme002