如何在纯Python代码(而不是kvlang)中使用Kivy Rotate?

如何在纯Python代码(而不是kvlang)中使用Kivy Rotate?,python,kivy,kivy-language,Python,Kivy,Kivy Language,我想用纯python代码而不是kvlang来旋转一个按钮 使用kvlang,我们可以旋转按钮,如中所示。 按钮围绕其自身中心旋转45度。以下是原始代码: from kivy.app import App from kivy.lang import Builder kv = ''' FloatLayout: Button: text: 'hello world' size_hint: None, None pos_hint: {'center

我想用纯python代码而不是kvlang来旋转一个按钮

使用kvlang,我们可以旋转按钮,如中所示。 按钮围绕其自身中心旋转45度。以下是原始代码:

from kivy.app import App
from kivy.lang import Builder
kv = '''
FloatLayout:
    Button:
        text: 'hello world'
        size_hint: None, None
        pos_hint: {'center_x': .5, 'center_y': .5}
        canvas.before:
            PushMatrix
            Rotate:
                angle: 45
                origin: self.center
        canvas.after:
            PopMatrix
'''
class RotationApp(App):
    def build(self):
        return Builder.load_string(kv)
RotationApp().run()
但当我尝试用纯python代码重写这个示例时,按钮会在其他地方旋转,如图所示:

上述两段代码产生的结果不同。我们做错什么了吗

更新:

该谜题由@increment建议解决,解决方案如下:

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.graphics import PushMatrix, PopMatrix, Rotate
class MyButton(Button):
    def __init__(self):
        super().__init__()
        self.text = 'hello world'
        self.size_hint = (None, None)
        self.pos_hint = {'center_x': .5, 'center_y': .5}
        with self.canvas.before:
            PushMatrix()
            
            # Rotate(origin=self.center, angle=45)  # previous approach
            self.rotation = Rotate(origin=self.center, angle=45)
            self.bind(center=lambda _, value: setattr(self.rotation, "origin", value))
            
        with self.canvas.after:
            PopMatrix()
class RotationApp(App):
    def __init__(self):
        super().__init__()
        self.layout = FloatLayout()
        self.button = MyButton()
        self.layout.add_widget(self.button)
    def build(self):
        return self.layout
RotationApp().run()

在Python代码中,
self.center
\uuuu init\uuuu
期间只计算一次。在kv代码中,会自动创建一个绑定,以便在每次更改
Rotate
指令的
origin
属性时重置该属性


您需要在Python代码中添加缺少的功能,比如
self.rotation=Rotate(…)
self.bind(center=lambda实例,value:setattr(self.rotation,“origin”,value))
(尽管我相信您可以想出一种更好的方法来设置它,这只是内联示例)。

在Python代码中,
self.center
\uuuuu init\uuuuu
过程中只计算一次。在kv代码中,会自动创建一个绑定,以便在每次更改
Rotate
指令的
origin
属性时重置该属性

您需要在Python代码中添加缺少的功能,比如
self.rotation=Rotate(…)
self.bind(center=lambda实例,value:setattr(self.rotation,“origin”,value))
(尽管我相信您可以想出更好的设置方法,这只是内联示例)

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.graphics import PushMatrix, PopMatrix, Rotate
class MyButton(Button):
    def __init__(self):
        super().__init__()
        self.text = 'hello world'
        self.size_hint = (None, None)
        self.pos_hint = {'center_x': .5, 'center_y': .5}
        with self.canvas.before:
            PushMatrix()
            
            # Rotate(origin=self.center, angle=45)  # previous approach
            self.rotation = Rotate(origin=self.center, angle=45)
            self.bind(center=lambda _, value: setattr(self.rotation, "origin", value))
            
        with self.canvas.after:
            PopMatrix()
class RotationApp(App):
    def __init__(self):
        super().__init__()
        self.layout = FloatLayout()
        self.button = MyButton()
        self.layout.add_widget(self.button)
    def build(self):
        return self.layout
RotationApp().run()