如何在纯 Python 代码(不是 kvlang)中使用 Kivy Rotate?
How to use Kivy Rotate in pure Python code (not kvlang)?
我想使用纯 python 代码而不是 kvlang 来旋转按钮。
使用 kvlang 我们可以旋转按钮,如 example 所示。
按钮围绕其自身中心旋转 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 代码重写此示例时,按钮在其他地方旋转,如图 here:
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)
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()
以上两段代码产生的结果不同。我们有没有做错什么?
更新:
按照@inclement的提示解题,解法如下:
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
在 __init__
期间仅计算一次。在kv代码中,会自动创建一个绑定来重置Rotate
指令的origin
属性每次改变。
您需要将缺少的功能放入 Python 代码中,例如 self.rotation = Rotate(...)
和 self.bind(center=lambda instance, value: setattr(self.rotation, "origin", value))
(尽管我相信您可以想出更好的方法来设置它向上,这只是内联示例)。
我想使用纯 python 代码而不是 kvlang 来旋转按钮。
使用 kvlang 我们可以旋转按钮,如 example 所示。 按钮围绕其自身中心旋转 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 代码重写此示例时,按钮在其他地方旋转,如图 here:
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)
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()
以上两段代码产生的结果不同。我们有没有做错什么?
更新:
按照@inclement的提示解题,解法如下:
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
在 __init__
期间仅计算一次。在kv代码中,会自动创建一个绑定来重置Rotate
指令的origin
属性每次改变。
您需要将缺少的功能放入 Python 代码中,例如 self.rotation = Rotate(...)
和 self.bind(center=lambda instance, value: setattr(self.rotation, "origin", value))
(尽管我相信您可以想出更好的方法来设置它向上,这只是内联示例)。