简体   繁体   中英

Events passing in python with kivy

I am new to python and kivy, I am trying to clear all widgets in a host when any button is pressed, my code is as follows:

from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.label import Label

spots={}

class spot(Button):
    '''
    classdocs
    '''
    def __init__(self, **kwargs):
        '''
        Constructor
        '''
        super(spot,self).__init__(**kwargs)
        self.ismine=False
        if 'text' in kwargs:
            self.text=kwargs['text']
        else:
            self.text="X"

    def on_press(self, *args, **kwargs):
        #return Button.on_press(self, *args, **kwargs)
        game.spottouched(self, self.text)

class game(BoxLayout):
    def __init__(self,**kwargs):
        super(game,self).__init__(**kwargs)
        self.m=minesholder(rows=25, cols=25)
        self.add_widget(self.m)
        self.attachtogrid()

    def attachtogrid(self):
        self.m.clear_widgets()
        spots.clear()
        for r in range(0,25):
            for c in range(0,25):
                idd=str(r)+","+str(c)
                spots[idd]=idd
                self.m.add_widget(spot(text=idd))

    def spottouched(self,spotid):
        #popup=Popup(title=spotid)
        #popup.open()
        self.clear_widgets()

The last line is for clearing the widgets, and spot class has the on_press event. I am trying to pass the event of on_press even of button on app to a holding boxlayout (game class), could you please tell/point me in right direction to lean on how pass the events?

Thank you.

game.spottouched(self, self.text)

You've misunderstood how python classes work. You want to clear the widgets from the instance of your game that you're actually using - something you created by writing game() . With a reference to that, you need to do instance.spottouched(spotid) to call the method of that instance.

What you're doing instead is calling the method via the class definition, which really makes no sense here and you don't want to do it. Actually, you basically never want to do this.

Anyway, the way to fix this depends on how you actually constructed your app, but it boils down to you need to keep a reference to the game instance somewhere that the spot instance can see it. The best way depends on the rest of your code, but you can always do it via the app class, eg

App.get_running_app().game = game()

and later

App.get_running_app().game.spottouched(self.text)

This is just an example, it might be a bad way to do things sometimes.

Also, begin your widget names with capital letters! kv language uses this to identify them, you will hit problems using it if you don't name them this way. It's also a strong python convention worth following.

I think this is what you want, based on your comment on @inclement's answer: Get rid of the on_press method on your button. You want to bind to the event instead - this will work more like WPF.

for r in range(0,25):
    for c in range(0,25):
        idd=str(r)+","+str(c)
        spots[idd]=idd
        s = spot(text=idd)
        self.m.add_widget(s)

        s.bind(on_press=self.spottouched)

So self.spottouched is like an event handler for the spot s on_press event.

s.bind(on_press=self.spottouched)

is kind of like this:

AddHandler s.Click, AddressOf spottouched

Note that adding the handler this way, the handler will receive a single argument which is the spot instance. You can get spot.text from that instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM