删除小部件后仍然存在HoverBehaviorButton

时间:2017-05-10 14:29:22

标签: python-3.x kivy kivy-language

Python 3.4.4 Kivy:1.9.1

我正在使用此hoverable.py(在底部找到的文件)为按钮创建mouse_pos事件以执行自定义动画。

然而,当我通过clear_widgets删除相关的小部件时,HoverButtons仍然存在,即使没有self.parent也是如此。我必须删除此按钮,因为我计划将此悬停事件扩展到其他小部件,并且不希望持久保存隐藏的小部件。

看看下面,让我知道我不理解的是什么。

简而言之,我想彻底删除HoverButton及其所有相关行为。



#main.py 

from win32api import GetSystemMetrics
from kivy.config import Config

Config.set('graphics', 'position', 'custom')
Config.set('graphics', 'resizable',  1)

from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout

from main_menu import MainMenu
from _map import Map

Builder.load_file('main_menu.kv')

class HoverBehaviorPersistance(App):

    boxlayout_main_menu = ObjectProperty(None)
    hover_button = ObjectProperty(None)
    
    def __init__(self, **kwargs):
        super(HoverBehaviorPersistance, self).__init__(**kwargs)
        self.content = BoxLayout()
        self.main_menu = MainMenu()
        self.content.add_widget(self.main_menu)

    def build(self):
        return self.content
        
    def begin(self):
        print("begin")
        self.test_map = Map()
        self.main_menu.boxlayout_main_menu.clear_widgets()
        self.main_menu.clear_widgets()
        self.content.clear_widgets()
        self.content.add_widget(self.test_map)
        
if __name__ == '__main__':
    HoverBehaviorPersistance().run()






#main_menu.py

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup

class MainMenu(BoxLayout):

    def __init__(self, **kwargs):
        super(MainMenu, self).__init__(**kwargs)
        print("Initializing MainMenu")
        
    def open_settings(self):
        settings_popup  = SettingsPopup()
        settings_popup.open()
        
class SettingsPopup(Popup):
    pass






#main_menu.kv

#: import HoverButton hover_widget_behavior

<MainMenu>
    boxlayout_main_menu:_boxlayout_main_menu
    hover_button:_hover_button
    orientation: 'vertical'
	
	AnchorLayout:
        anchor_x: 'center'
	    anchor_y: 'center'
		
        BoxLayout:
            id:_boxlayout_main_menu
		orientation: 'vertical'
	        spacing: 10
		padding: 10
		size_hint: .5, .8
			
		HoverButton:
                id:_hover_button
		    text: 'begin'
		    on_release: app.begin()
            HoverButton:
                text: 'settings'
                on_release: root.open_settings()
				
<SettingsPopup>
    id: popup_settings
	size_hint: 0.9, 0.6
	title: "Settings"
	GridLayout:
	
	    cols: 2
		
	    Label:
		text:'Settings #1'
	    Slider:
	        orientation: 'horizontal'
		value: 25
		max: 100
		min: 0
	    Label:
		text: 'Settings #2'
	    BoxLayout:
		orientation: 'horizontal'
	    Label:
		text: 'Settings #3'
&#13;
&#13;
&#13;

&#13;
&#13;
#_map.py

from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

class Map(BoxLayout):
    
    def __init__(self, **kwargs):
        super(Map, self).__init__(**kwargs)
        print("Map initiated.")
		
        self.btn = Button(text="btn")
        self.add_widget(self.btn)
&#13;
&#13;
&#13;

&#13;
&#13;
#hover_widget_behavior.py

from kivy.animation import Animation
from kivy.core.window import Window
from kivy.properties import BooleanProperty, ObjectProperty, StringProperty
from kivy.uix.button import Button


class HoverGUIBehavior(object):
    #__author__ = 'Olivier POYEN'
    """Hover behavior.

    :Events:
        `on_enter`
            Fired when mouse enter the bbox of the widget.
        `on_leave`
            Fired when the mouse exit the widget 
    """

    hovered = BooleanProperty(False)
    border_point= ObjectProperty(None)
    '''Contains the last relevant point received by the Hoverable. This can
    be used in `on_enter` or `on_leave` in order to know where was dispatched the event.
    '''

    def __init__(self, **kwargs):
        self.register_event_type('on_enter')
        self.register_event_type('on_leave')
        Window.bind(mouse_pos=self.on_mouse_pos)
        super(HoverGUIBehavior, self).__init__(**kwargs)

    def on_mouse_pos(self, *args):
        pos = args[1]
        inside = self.collide_point(*pos)
        if self.hovered == inside:
            #We have already done what was needed
            return
        self.border_point = pos
        self.hovered = inside
        if inside:
            self.dispatch('on_enter')
        else:
            self.dispatch('on_leave')

    def on_enter(self):
        pass

    def on_leave(self):
        pass
        
class HoverButton(Button, HoverGUIBehavior):    
    
    # TODO: HoverButton somehow still exists even after removing parent and it's children
    def on_enter(self, *args, **kwargs):
        print("I'm still here!")
        if not self.parent: # Find someway to remove itself
            print()
            print('self = ' + str(self))
            print("I'm definitely still here!")
            return
        self.ref_x = self.x
        self.ref_y = self.y
        
        self.anim = Animation(x = self.x -10 ,y = self.y - 10, duration=1.0, t='out_bounce') + Animation(x = self.x + 10, y = self.y + 10, duration=1.0, t='out_bounce')
        self.anim.repeat = True
        self.anim.start(self)

    def on_leave(self, *args):
        if not self.parent: # Find someway to remove itself 
            print()
            print('self = ' + str(self))
            print("I'm definitely still here!")
            return
        if self.anim:
            self.anim.cancel(self)
            return_anim = Animation(pos = (self.ref_x, self.ref_y), duration = 0.35, t='out_bounce')
            return_anim.start(self)
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我已经解决了我的问题。

问题在于我没有意识到在不同布局之间转换时我必须取消绑定功能。

对于hover_widget_behavior.py,如果我删除它的父母(例如,如果不是self.parent :),我所要做的就是解除绑定(取消绑定on_mouse_pos)。

现在,每当我删除/重新创建布局时,我都没有获得on_mouse_pos。

#hover_widget_behavior.py

from kivy.animation import Animation
from kivy.core.window import Window
from kivy.properties import BooleanProperty, ObjectProperty, StringProperty
from kivy.uix.button import Button


class HoverGUIBehavior(object):
    #__author__ = 'Olivier POYEN'
    """Hover behavior.

    :Events:
        `on_enter`
            Fired when mouse enter the bbox of the widget.
        `on_leave`
            Fired when the mouse exit the widget 
    """

    hovered = BooleanProperty(False)
    border_point= ObjectProperty(None)
    '''Contains the last relevant point received by the Hoverable. This can
    be used in `on_enter` or `on_leave` in order to know where was dispatched the event.
    '''

    def __init__(self, **kwargs):
        self.register_event_type('on_enter')
        self.register_event_type('on_leave')
        Window.bind(mouse_pos=self.on_mouse_pos)
        super(HoverGUIBehavior, self).__init__(**kwargs)

    def on_mouse_pos(self, *args):
#==========================================================
        # Insert this statement to unbind itself its
        # parent does not exist
        if not self.parent:
            print("No self.parent")
            Window.unbind(mouse_pos=self.on_mouse_pos)
            return
#==========================================================
        pos = args[1]
        inside = self.collide_point(*pos)
        if self.hovered == inside:
            #We have already done what was needed
            return
        self.border_point = pos
        self.hovered = inside
        if inside:
            self.dispatch('on_enter')
        else:
            self.dispatch('on_leave')

    def on_enter(self):
        pass

    def on_leave(self):
        pass

class HoverButton(Button, HoverGUIBehavior):

    # TODO: HoverButton somehow still exists even after removing parent and it's children
    def on_enter(self, *args, **kwargs):
        print("I'm still here!")
        if not self.parent: # Find someway to remove itself
            print()
            print('self = ' + str(self))
            print("I'm definitely still here!")
            return
        self.ref_x = self.x
        self.ref_y = self.y

        self.anim = Animation(x = self.x -10 ,y = self.y - 10, duration=1.0, t='out_bounce') + Animation(x = self.x + 10, y = self.y + 10, duration=1.0, t='out_bounce')
        self.anim.repeat = True
        self.anim.start(self)

    def on_leave(self, *args):
        if not self.parent: # Find someway to remove itself 
            print()
            print('self = ' + str(self))
            print("I'm definitely still here!")
            return
        if self.anim:
            self.anim.cancel(self)
            return_anim = Animation(pos = (self.ref_x, self.ref_y), duration = 0.35, t='out_bounce')
            return_anim.start(self)