如何解决在另一个类中使用 Window.bind 时,Kivy Config.read 无法正常工作
我刚刚发现了一个错误,正在努力寻找解决方案。这是我的文件夹结构:
|- root
|- GUI.py
|- GUI.ini
|- layouts
|- root.kv
|- style.kv
|- lib
|- kivy_utils.py
|- static
|- icon.ico
|- Barlow-Regular.ttf
|- Barlow-Bold.ttf
GUI.py 是我启动 GUI 的起点,如下所示:
# %% standard python library imports
import os
# %% kivy imports
# import kivy
from kivy.app import App
from kivy.core.window import Window
from kivy.config import Config
from kivy.lang import Builder
from kivy.uix.Boxlayout import BoxLayout
# %% lib imports
from lib.kivy_utils import TTLabel
# read & overrule config
Config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)),"GUI.ini"))
Window.size = Config.getint("graphics","width"),Config.getint("graphics","height")
# read kv language files
for kv in ["root.kv","style.kv"]:
Builder.load_file("layouts" + os.sep + kv)
class Root(BoxLayout):
""" Main Root class for callbacks,UI building etc."""
def __init__(self):
super().__init__()
def test_function(self):
print("K TEST")
class Launcher(App):
"""Supplementary Launcher class"""
def build(self):
return Root()
def on_pause(self):
return True
if __name__ == "__main__":
Launcher().run()
我想将 kivy_utils.py 用于自定义类,例如可扩展的小部件、工具提示等:
from kivy.properties import BooleanProperty,ObjectProperty,NumericProperty
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.slider import Slider
from kivy.uix.switch import Switch
from kivy.clock import Clock
class Tooltip(Label):
pass
class HoverBehavior(object):
"""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)
def __init__(self,**kwargs):
self.register_event_type('on_enter')
self.register_event_type('on_leave')
Window.bind(mouse_pos=self.on_mouse_pos) # for recognizing tooltips
super(HoverBehavior,self).__init__(**kwargs)
def on_mouse_pos(self,*args):
if not self.get_root_window():
return
pos = args[1]
inside = self.collide_point(*self.to_widget(*pos)) # compensate for relative layout
if self.hovered == inside:
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 TTLabel(HoverBehavior,Label):
"""Resizable Label with Tooltip on top of Label and HoverBehavIoUr class"""
def __init__(self,**kwargs):
super().__init__()
self.tooltip = None # Attribute set in kv file
self.header = None # Attribute set in kv file
self.tooltip_wdg = Tooltip()
Window.bind(on_resize=self.on_window_resize) # binds font_size rescaling function to on_resize event
Clock.schedule_once(self.on_window_resize,1.5) # called once at init cuz widget hasnt final size yet
def on_enter(self):
"""Event fires when entering widget"""
if self.tooltip: # only binds event if tooltip variable is set
Window.bind(mouse_pos=lambda w,p: setattr(self.tooltip_wdg,'pos',p)) # binds position to cursor
self.tooltip_wdg.text = self.tooltip # sets text to tooltip variable
Window.add_widget(self.tooltip_wdg)
def on_leave(self):
"""Event fires when leaving widget"""
if self.tooltip:
Window.remove_widget(self.tooltip_wdg)
def on_window_resize(self,*args):
"""Event fires when window is rescaled"""
fire_refresh = True
# # Fires when horizontal size is too small
if self.size[0] < self._label.size[0]:
fire_refresh = False
self.texture_size[0] = self.size[0] # reduce texture size to widget size
if self.size[1] < self._label.size[1]: # additionally,if vertical size is too small,reduce aswell
self.texture_size[1] = self.size[1]
return
# Fires when vertical size is too small
if self.size[1] < self._label.size[1]:
fire_refresh = False
self.texture_size[1] = self.size[1]
if self.size[0] < self._label.size[0]:
self.texture_size[0] = self.size[0]
return
# Fires when widget size > texture size # Todo: is there another way not to fire all the time?
if fire_refresh:
self.texture_update()
最后,我的 root.kv 看起来像这样:
<Root>:
BoxLayout:
orientation: 'horizontal'
Button:
text: "Test button"
on_release: root.test_function()
TTLabel:
text: "Test label with tooltip"
tooltip: "Also WOW!"
现在我的实际问题是:代码有效,但是(!)我的 Config.read
文件中的 GUI.py
命令没有“刷新”当前配置 - 加载有效,我可以访问通过 Config.get
使用属性,使用 Config.write
等 - .ini 文件已更新,但未实现更改。现在我想手动刷新配置中的参数(例如Window.size = Config.getint("graphics","height")
),但我想使用选项菜单(F1),我确信肯定有另一种方式。一旦我在 Window.bind
中使用 kivy_utils.py
,问题就会出现。我尝试在那里加载配置,使用 self.get_root_window
而不是 Window
,将 Config.read
命令放在 kivy_utils.py
等的不同位置。我错过了什么?
解决方法
我想通了 - 我只需要在 Window
导入之前导入并阅读配置:
from kivy.config import Config
Config.read("GUI.ini")
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
像这样,您可以使用配置器 (F1) 并正确识别受影响的更改(但是,在重新启动 UI 之后)。我还发现了环境变量的奇怪行为:kivy documentation 状态:
如果不想映射任何环境变量,可以禁用 行为::
os.environ["KIVY_NO_ENV_CONFIG"] = "1"
他们可能在那里翻转了一个布尔值,因为 0 实际上禁用了环境变量,而 1 启用了它们。将报告给 kivy 存储库。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。