微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python KIvy 旋转矩形在调整大小时移动

如何解决Python KIvy 旋转矩形在调整大小时移动

我有一个旋转的矩形,当我调整它的大小时,它会稍微改变它的位置。 但我不希望它移动...

发生这种位置变化,当我重置中心时,如果我不改变中心,它不会移动,但对我来说中心是正确的很重要。

我创建了 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 的一个角进行的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。