问题描述
我有一个旋转的矩形,当我调整它的大小时,它会稍微改变它的位置。 但我不希望它移动...
发生这种位置变化,当我重置中心时,如果我不改变中心,它不会移动,但对我来说中心是正确的很重要。
我创建了 2 个视频。 这是目前:https://youtu.be/TqY3Ji0rnLw 这就是我想要的(我删除了中心重置,但正如我之前说过的,我想要一个中心重置):https://youtu.be/Jfq777nzu6o
我该如何解决这个问题?
这是我的代码:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color,Rectangle,Pushmatrix,Rotate,PopMatrix
from kivy.clock import Clock
from kivy.core.window import Window
class Canvas:
def __init__(self,root,pos,size,rotation=0,color=(1,1)):
with root.canvas:
Pushmatrix()
self._color_instruction = Color(rgba=color)
self._rotation_instruction = Rotate(angle=rotation,origin=(150,150))
self._rectangle_instruction = Rectangle(pos=pos,size=size)
PopMatrix()
@property
def center(self):
pos = self.pos
size = self.size
center_x = pos[0] + size[0] / 2
center_y = pos[1] + size[1] / 2
return (center_x,center_y)
@property
def pos(self):
return self._rectangle_instruction.pos
@pos.setter
def pos(self,value):
self._rectangle_instruction.pos = value
self._rotation_instruction.origin = self.center
@property
def size(self):
return self._rectangle_instruction.size
@size.setter
def size(self,value):
self._rectangle_instruction.size = value
self._rotation_instruction.origin = self.center
@property
def rotation(self):
return self._rotation_instruction.angle
@rotation.setter
def rotation(self,value):
self._rotation_instruction.angle = value
@property
def color(self):
return self._color_instruction.rgba
@color.setter
def color(self,value):
self._color_instruction.rgba = value
class Root(Widget):
def __init__(self,**kwargs):
super(Root,self).__init__(**kwargs)
self.rectangle = Canvas(self,(100,100),rotation=45)
self.keys_pressed = set()
self._keyboard = Window.request_keyboard(self._on_keyboard_closed,self)
self._keyboard.bind(on_key_down = self._on_key_down)
self._keyboard.bind(on_key_up = self._on_key_up)
Clock.schedule_interval(self.step,0)
def step(self,dt):
x = self.rectangle.pos[0]
y = self.rectangle.pos[1]
width = self.rectangle.size[0]
height = self.rectangle.size[1]
rotation = self.rectangle.rotation
step_size = 300 * dt
if "up" in self.keys_pressed:
y += step_size
if "left" in self.keys_pressed:
x -= step_size
if "right" in self.keys_pressed:
x += step_size
if "down" in self.keys_pressed:
y -= step_size
if "y" in self.keys_pressed:
rotation += step_size
if "x" in self.keys_pressed:
rotation -= step_size
if "w" in self.keys_pressed:
height = min(height + step_size,300)
if "a" in self.keys_pressed:
width = max(width - step_size,10)
if "d" in self.keys_pressed:
width = min(width + step_size,300)
if "s" in self.keys_pressed:
height = max(height - step_size,10)
self.rectangle.pos = (x,y)
self.rectangle.size = (width,height)
self.rectangle.rotation = rotation
def _on_keyboard_closed(self):
self._keyboard.unbind(_on_key_down = self._on_key_down)
self._keyboard.ubind(_on_key_up = self._on_key_up)
self._keyboard = None
def _on_key_down(self,keyboard,keycode,text,modifiers):
self.keys_pressed.add(text if text != None else keycode[1])
def _on_key_up(self,keycode):
if keycode[1] in self.keys_pressed:
self.keys_pressed.remove(keycode[1])
class TestApp(App):
def __init__(self,**kwargs):
super(TestApp,self).__init__(**kwargs)
def build(self):
return Root()
def main():
app = TestApp()
app.run()
if __name__ == "__main__":
main()
我该如何改变它在第二个视频中的位置?
解决方法
这是您的代码的修改版本,它使用 kv
和现有的 canvas
对象来绘制 Rectangle
:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import ListProperty,NumericProperty
from kivy.uix.widget import Widget
from kivy.clock import Clock
from kivy.core.window import Window
class MyCanvas(Widget):
color = ListProperty([1,1])
rotation = NumericProperty(0)
Builder.load_string('''
<MyCanvas>:
size_hint: None,None
canvas:
Color:
rgba: self.color
PushMatrix:
Translate:
xy: self.x,self.y
Rotate:
axis: 0,1
origin: 0,0
angle: self.rotation
Scale:
origin: 0,0
xyz: self.width,self.height,1
Rectangle: # unit rectangle centered on origin
pos: -0.5,-0.5
size: 1,1
PopMatrix:
''')
class Root(Widget):
def __init__(self,**kwargs):
super(Root,self).__init__(**kwargs)
# self.rectangle = Canvas(self,(100,100),rotation=45)
self.rectangle = MyCanvas(pos=(100,size=(100,rotation=45)
self.add_widget(self.rectangle)
self.keys_pressed = set()
self._keyboard = Window.request_keyboard(self._on_keyboard_closed,self)
self._keyboard.bind(on_key_down = self._on_key_down)
self._keyboard.bind(on_key_up = self._on_key_up)
Clock.schedule_interval(self.step,0)
def step(self,dt):
x = self.rectangle.pos[0]
y = self.rectangle.pos[1]
width = self.rectangle.size[0]
height = self.rectangle.size[1]
rotation = self.rectangle.rotation
step_size = 300 * dt
if "up" in self.keys_pressed:
y += step_size
if "left" in self.keys_pressed:
x -= step_size
if "right" in self.keys_pressed:
x += step_size
if "down" in self.keys_pressed:
y -= step_size
if "y" in self.keys_pressed:
rotation += step_size
if "x" in self.keys_pressed:
rotation -= step_size
if "w" in self.keys_pressed:
height = min(height + step_size,300)
if "a" in self.keys_pressed:
width = max(width - step_size,10)
if "d" in self.keys_pressed:
width = min(width + step_size,300)
if "s" in self.keys_pressed:
height = max(height - step_size,10)
self.rectangle.pos = (x,y)
self.rectangle.size = (width,height)
self.rectangle.rotation = rotation
def _on_keyboard_closed(self):
self._keyboard.unbind(_on_key_down = self._on_key_down)
self._keyboard.ubind(_on_key_up = self._on_key_up)
self._keyboard = None
def _on_key_down(self,keyboard,keycode,text,modifiers):
self.keys_pressed.add(text if text != None else keycode[1])
def _on_key_up(self,keycode):
if keycode[1] in self.keys_pressed:
self.keys_pressed.remove(keycode[1])
class TestApp(App):
def __init__(self,**kwargs):
super(TestApp,self).__init__(**kwargs)
def build(self):
return Root()
def main():
app = TestApp()
app.run()
if __name__ == "__main__":
main()
Rectangle
的大小与您的视频显示的不完全一样,但很接近。
您可以通过将 kv
更改为:
<MyCanvas>:
size_hint: None,None
canvas.before:
PushMatrix:
Rotate:
axis: 0,1
origin: self.pos
angle: self.rotation
canvas:
Color:
rgba: self.color
Rectangle:
pos: self.pos
size: self.size
canvas.after:
PopMatrix:
但这会影响旋转行为,因此旋转是围绕 Rectangle
而不是 center
的一个角进行的。