1

Let's pretend I am building a tic-tac-toe game (becouse it's pretty similar as a structure) I want the result to be shown in a popup, with a new game button, and I want this popup to let me access settings (with another button) and change them, always staying within the popup, then leave and finally close it and start a new game.

I wish i could keep things ordered and therefore have a separate popup class where i can build my custom popup.

I have the newgame method and reset method as method of my game-grid class, as obvious. Methods for changing settings are, on the other hand, on a custom settings class

While designing the popup class how can I bind it's buttons (e.g new game) to methods that are contained on a completly different class? I've looked on some kv examples and they usually use root.blabla.method to acces a method that is in a different position of the same tree (in the .kv file) but here the methods I am trying to reach are out of the tree!

I'll try to put some example code to make it more clear

class Settings():

    def changeSettings(self):
        ....

class GmeGrid(GridLayout):

    def newGame(self):
        ....

    def reset(self):
        ...

class customPopup(Popup):

    pass

Then, on a .kv file I wish I could bind some popup's buttons to the newGame and change settings methods

The problem here is that I should bind buttons on the popop class to the mothods of completly different class and I don't know how to to that (on the .kv file especially)

UfoRobot
  • 100
  • 3
  • 9

1 Answers1

1

As long as the widget has been fully instantiated and added to the widget tree, you can use self.parent to access the widget's parent. You might look into passing references instead though:

Builder.load_string('''
<CustomPopup>:
    BoxLayout:
        orientation: 'vertical'
        # some settings stuff here
        BoxLayout:
            orientation: 'horizontal'
            Button:
                text: 'New Game'
                on_press: root.do_new_game()
''')

class CustomPopup(Popup):
    settings_widget = ObjectProperty()
    new_game = ObjectProperty()

    def do_new_game(self):
        self.settings_widget.some_property = some_value
        self.dismiss()
        self.new_game()

p = CustomPopup(settings_widget=my_widget, new_game=mygame.newGame)
p.open()

This is better that assuming the parent has the settings, because if you change where you keep the settings, you just need to change one reference.

kitti
  • 14,663
  • 31
  • 49
  • Well that isn't what I really ment. This way I could acces the settings class method inside the popup (as the settings class is a member of it) but not any method which isn't "under" the popup class (as for eg a new game method) self.parent allows me to climb the tree one level but for more than one level? I may edit the question to get the point more clear. Thank you anyway – UfoRobot May 21 '14 at 11:50
  • @AscanioFX I added an example for referencing a method. – kitti May 21 '14 at 14:30
  • @RyanP Thank you! Mmm I find your solution really interesting! That way I would pass my settings widget and any function i might need to the CustomPopup class when initializing it. I haven't fully understood what kivy properties are but that's not the topic of this question. If I pass my_widget to the CustomPopup would it create a copy of it (without changing the original setting widget when beeing modified) or modified it as "by reference" (I come from a C background) – UfoRobot May 21 '14 at 19:34
  • Everything in Python is passed by object reference. Think of these as magical pointers which automatically reference/dereference themselves. So if you pass `my_widget` to `CustomPopup` it will be a separate pointer containing the same value (the same reference). – kitti May 21 '14 at 19:53
  • This is a nice little article describing the differences between pass by value, pass by reference, and pass by object-reference. http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/ – kitti May 21 '14 at 19:55