【问题标题】:Python KIvy roated rectangle moves on resizePython KIvy 旋转矩形在调整大小时移动
【发布时间】:2021-03-21 21:20:43
【问题描述】:

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

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

我创建了 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, 0, 0, 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), (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, keyboard, 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()

如何改变它在第二个视频中的位置?

【问题讨论】:

    标签: python rotation kivy resize rectangles


    【解决方案1】:

    这是您的代码的修改版本,它使用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,0,0,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,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), (100, 100), rotation=45)
            self.rectangle = MyCanvas(pos=(100,100), size=(100,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, keyboard, 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,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

    【讨论】:

    • 谢谢:)。但在这两个方向上调整大小,但我希望它只向一个方向移动。我该怎么做?
    • 是的,但不幸的是原点没有设置为实际中心,所以如果我通过按 k 或 y 键更改旋转,它将围绕 pos 旋转而不是围绕矩形的中心
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多