Jeff
Jeff

Reputation: 591

Kivy: how do I clear the changes on a screen if they were not saved

I currently have a main page and a settings page. In screen manager, when i go to the settings page and change a value without clicking the save button and leave the settings page, it looks as though the settings were saved to the end user because when they return to that screen, their changes still reflect whereas they have not clicked save. How do i tackle this issue.

I tried clearing the widgets and recreate them but i failed. Seems like Kivy runs a on_pre_leave event same time it runs a on_pre_enter event. To solve this issue it would be nice if the settings would be saved when they exit the screen OR their changes cleared when they exit the screen without clicking save. Please help:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.switch import Switch
from kivy.core.window import Window
from kivy.uix.progressbar import ProgressBar
from kivy.clock import Clock

Window.clearcolor = (252, 235, 233, 0)
#!/usr/bin/python3

class MyScreenManager(ScreenManager):
    pass


class LoginPageScreen(Screen):
    pass
class UserSettingsScreen(Screen):
    pass

class LoginPage(BoxLayout):
    def __init__(self, **kwargs):
        super(LoginPage, self).__init__(**kwargs)

        self.add_widget(Label(text="[color=000000][b]Main page[/b][/color]", markup=True, size_hint_y=None, font_size='15sp'))

class UserSettings(BoxLayout):
    def __init__(self, **kwargs):
        super(UserSettings, self).__init__(**kwargs)
        # self.clear_widgets()
        on_pre_enter = self.userSettingsClass()
        # on_pre_leave = self.userSettingsClass()

    def userSettingsClass(self):
        # self.clear_widgets()

        self.add_widget(Label(text="[color=000000][b]settings[/b][/color]", markup=True, font_size='15sp'))
        self.testSwitch = Switch()
        self.add_widget(self.testSwitch)

        self.add_widget(Button(text='Save', font_size=40, size_hint_y=None, height=80, on_press=self.updateSettings))

    def updateSettings(self, btn):
        print('this is how i currently save settings, if the user does not click this button and come back to this page'
              ' it looks as though they saved the settings when they really did not')



root_widget = Builder.load_string('''
#:import NoTransition kivy.uix.screenmanager.NoTransition
#:import sys sys
MyScreenManager:
    transition: NoTransition()

    LoginPageScreen:
        ActionBar:
            pos_hint: {'top':1}
        ActionBar:
            pos_hint: {'top':0.07}
            ActionView:
                ActionPrevious:
                    with_previous: False
                ActionOverflow:
                ActionGroup:
                    ActionButton:
                        text: 'Settings'
                        on_release: app.root.current = 'settings'

    UserSettingsScreen:
        ActionBar:
            pos_hint: {'top':1}
        ActionBar:
            pos_hint: {'top':0.07}
            ActionView:
                ActionPrevious:
                    with_previous: True
                    on_release: app.root.current = 'home'


<UserSettingsScreen>:
    name: 'settings'
    # on_pre_enter: userSettingsClass()
    BoxLayout:
        size_hint_y: 0.85
        pos_hint: {'center_y': .5}
        #size_hint: (None, None)
        ScrollView:
            UserSettings
                orientation: 'vertical'
                padding: [50,10,50,10]
                spacing: 10
                # size_hint: (None, None)
                size: (1080, 3000)

<LoginPageScreen>:
    name: 'home'
    BoxLayout:
        LoginPage
            orientation: 'vertical'
            padding: [50,10,50,10]
            spacing: 10
            # size_hint_y: 0.9

''')

class ScreenManagerApp(App):
    def build(self):
        return root_widget

ScreenManagerApp().run()

Upvotes: 2

Views: 1859

Answers (1)

PalimPalim
PalimPalim

Reputation: 3048

Kivy.uix.settings

Firstly, have a look at https://kivy.org/docs/api-kivy.uix.settings.html It works quite nicely and can easily be customized. For an example see folder 6-09-12_settings here https://github.com/oreillymedia/creating_apps_in_kivy which is part of the zip file. These are codes for the book, but I think the code alone can be of great help. too.

Your solution

If you want to stick with what you have, you can implement something similar to the app below. It is a simplified version of your app and works with a global for the status of the button.

enter image description here

from kivy.app import App
from kivy.lang import Builder

from kivy.uix.screenmanager import ScreenManager, Screen

from kivy.properties import BooleanProperty
from kivy.uix.popup import Popup

SWITCH_STATUS = False

#!/usr/bin/python3

class MyScreenManager(ScreenManager):
    pass

class SettingsScreen(Screen):
    saved = BooleanProperty()
    def update_on_enter(self):
        global SWITCH_STATUS
        self.ids.switch.active = SWITCH_STATUS
        self.saved = False

    def save(self):
        global SWITCH_STATUS
        SWITCH_STATUS = self.ids.switch.active
        self.saved = True

    def transition_to_login(self):
        print(self.saved)
        global SWITCH_STATUS
        if not self.saved and not SWITCH_STATUS==self.ids.switch.active:
            CheckPopup().open()
        else:
            self.parent.current = 'login'


class CheckPopup(Popup):
    pass


kv_str = Builder.load_string('''
MyScreenManager:

    Screen:
        name: 'login'
        BoxLayout:
            Label:
                text: 'login'
            Button:
                text: 'go to Settings'
                on_press: root.current = 'settings'
    SettingsScreen:

<SettingsScreen>:
    name: 'settings'
    on_pre_enter: self.update_on_enter()


    BoxLayout:
        Switch:
            id: switch
        Button:
            id: savebutton
            text: 'save'
            on_press: root.save()
        Button:
            text: 'go to login'
            on_press: root.transition_to_login()

<CheckPopup>:
    title: 'unsaved changes'
    size_hint: None, None
    size: 500, 500 
    BoxLayout:
        Button:
            text: 'discard changes'
            on_press: app.root.current = 'login'; root.dismiss()
        Button:
            text: 'return to Settings'
            on_press: root.dismiss()

''')

class ScreenManagerApp(App):
    def build(self):
        return kv_str

ScreenManagerApp().run()

Upvotes: 1

Related Questions