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;
#_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;
#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;
答案 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)