Это обычно возникает при использовании системы сборки, такой как Apache Ant , которая только компилирует java-файлы, когда java-файл является более новым, чем файл класса. Если подписи метода изменяются, а классы используют старую версию, вещи не могут быть скомпилированы правильно. Обычным решением является полная перестройка (обычно «ant clean», затем «ant»).
Иногда это также может быть вызвано при компиляции с одной версией библиотеки, но работает с другой версией.
Реализация кода, который вам требуется:
from kivy.config import Config
from kivy.core.window import Window
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.graphics import Rectangle, Color
mainscreen = BoxLayout(orientation='vertical')
label1 = Label(text='label_1', font_size=18, color=(0, 0, 0, 1), size_hint=(None, None))
label1.bind(texture_size=label1.setter('size'))
def update_rect(instance, *args):
rect.pos = instance.pos
rect.size = instance.size
with label1.canvas.before:
Color(1, .5, 0, 1)
rect = Rectangle(pos=label1.pos, size=label1.size)
label1.bind(pos=update_rect, size=update_rect)
label2 = Label(text='label_2', color=(0, 0, 0, 1))
mainscreen.add_widget(label1)
mainscreen.add_widget(label2)
class MyApp(App):
def build(self):
return mainscreen
if __name__ == '__main__':
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
Window.clearcolor = (1, 1, 1, 1)
MyApp().run()
ИМХО реализация в kv более читаема и более гибка, когда выполняется связывание, как в случае метки, которая соответствует размеру. [1113 ]
from kivy.config import Config
from kivy.core.window import Window
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.graphics import Rectangle, Color
from kivy.properties import ListProperty
class CustomLabel(Label):
bgcolor = ListProperty([0, 0, 0, 1])
def __init__(self, **kwargs):
if kwargs.get('bgcolor'):
self.bgcolor = kwargs['bgcolor']
kwargs.pop('bgcolor')
super(CustomLabel, self).__init__(**kwargs)
self.bind(texture_size=self.setter('size'))
with self.canvas.before:
self.p = Color(*self.bgcolor)
self.rect = Rectangle(pos=self.pos, size=self.size)
self.on_bgcolor()
self.bind(pos=self.geometry_bind, size=self.geometry_bind)
def on_bgcolor(self, *args):
self.p.rgba = self.bgcolor
def geometry_bind(self, *args):
self.rect.pos = self.pos
self.rect.size = self.size
class MyApp(App):
def build(self):
mainscreen = BoxLayout(orientation='vertical')
label1 = CustomLabel(text='label_1', font_size=18, color=(0, 0, 0, 1), size_hint=(None, None), bgcolor=(1, .5, 0, 1))
label2 = Label(text='label_2', color=(0, 0, 0, 1))
mainscreen.add_widget(label1)
mainscreen.add_widget(label2)
return mainscreen
if __name__ == '__main__':
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
Window.clearcolor = (1, 1, 1, 1)
MyApp().run()
Объяснение:
bind
: функция bind(foo_property = callback)
отвечает за вызов обратного вызова когда изменяется foo_property.
setter
: функция setter('foo_property')
генерирует обратный вызов, который позволяет вам установить значение.
Если вы присоединитесь к обеим функциям:
class FooClass(Foo_EventDispatcher):
property_a = FooProperty(initial_value_a)
property_b = FooProperty(initial_value_b)
def __init__(self, **kwargs):
super(FooClass, self).__init__(**kwargs)
self.bind(property_a=self.setter('property_b'))
эквивалентно следующей инструкции в .kv:
<FooClass>:
property_b: self.property_a
Еще один способ решить мою проблему - решение, основанное на ответе @ eyllanesc и видео с киви-курса о киви . Я публикую это здесь по двум причинам: (1) с этой версией можно ясно видеть, что происходит - как и когда фон нарисован на самом деле - без другого синтаксического слоя (язык kivy) и без полностью bind
и setter
Новое для меня, (2) eyllanesc предоставил немного грязный код Python.
Код:
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
from kivy.app import App
class LabelWithBackground(Label):
def __init__(self, bgcolor, **kwargs):
super().__init__(**kwargs)
self.bgcolor = bgcolor
self.draw_background()
def draw_background(self):
if self.canvas is not None:
self.canvas.before.clear()
with self.canvas.before:
Color(*self.bgcolor)
Rectangle(pos=self.pos, size=self.size)
def on_size(self, *args):
self.draw_background()
def on_pos(self, *args):
self.size = self.texture_size
self.draw_background()
class MyApp2(App):
def __init__(self):
super().__init__()
self.layout = BoxLayout()
self.layout.orientation = 'vertical'
self.labels = [
Label(text='label_0', color=(0, 0, 0, 1)),
LabelWithBackground(text='label_1', color=(0, 0, 0, 1), size_hint=(.5, None), bgcolor=(1, .5, 0, 1)),
Label(text='label_2', color=(0, 0, 0, 1)),
LabelWithBackground(text='label_3', color=(0, 0, 0, 1), size_hint=(None, .25), bgcolor=(1, .5, 0, 1)),
Label(text='label_4', color=(0, 0, 0, 1)),
LabelWithBackground(text='label_5', color=(0, 0, 0, 1), size_hint=(None, None), bgcolor=(1, .5, 0, 1))]
for lbl in self.labels:
self.layout.add_widget(lbl)
def build(self):
return self.layout
if __name__ == '__main__':
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
Window.clearcolor = (1, 1, 1, 1)
MyApp2().run()
Как это выглядит: