【问题标题】:How to rotate two rectangle widgets independently on single screen in kivy?如何在kivy的单个屏幕上独立旋转两个矩形小部件?
【发布时间】:2020-01-20 14:50:50
【问题描述】:

我正在学习 Python 编程并开发一个简单的游戏应用程序,在该应用程序中,我需要在单个屏幕上单击它们时旋转两个矩形,但发生的情况是当我单击其中一个矩形时,两个矩形都沿原点旋转正在单击的那个矩形,但另一个矩形不是这种情况,实际上它的位置也不是应该的,并且当单击分配的位置(该矩形不存在的位置)时,它会在不旋转的情况下旋转两个矩形。我只需要在独立点击时旋转两个矩形。 很难解释,所以请尝试执行代码并找出发生了什么。

from kivy.app import App
from kivy.graphics import Rotate, Rectangle, Ellipse, Color
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, CardTransition
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, NumericProperty, ReferenceListProperty, ListProperty
from kivy.uix.floatlayout import FloatLayout

Builder.load_string('''

<Stage_2>:
    object2: Object2
    object3: Object3

    Object2:
        id: Object2
        center: self.rotate_origin

    Object3:
        id: Object3
        center: self.rotate_origin

<Manager>:
    id: screen_manager

    Screen:
        name:"P"
        FloatLayout:

            Button:
                pos_hint:{"x":0.2,"y":0.05}
                size_hint: 0.6, 0.2
                font_size: (root.width**2 + root.height**2) / 13**4
                text: "Play"
                background_color: 255,0,1,1
                on_release:
                    root.transition.direction = "up"        
                    root.current = "stage2"

    Screen:
        name: 'stage2'
        Stage_2:
            id:s2

''')

class Object2(Widget):
    def __init__(self, *args, **kwargs):
        Widget.__init__(self, *args, **kwargs)
        self.rect_pos_x = 500
        self.rect_pos_y = 425
        self.rect_pos = self.rect_pos_x, self.rect_pos_y
        self.rect_width = 150
        self.rect_height = 30
        self.rect_size = self.rect_width, self.rect_height
        self.rotate_origin_x = self.rect_pos_x + self.rect_width / 2
        self.rotate_origin_y = self.rect_pos_y + self.rect_height / 2
        self.rotate_origin = self.rotate_origin_x, self.rotate_origin_y
        self.angle = 135
        print('rect 1')
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0,197,68))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def rotate(self):
        self.canvas.clear()
        self.angle += 90
        if (self.angle > 315):
            self.angle = 225
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0, 255, 100))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            self.rotate()
            print(self.angle)
class Object3(Widget):
    def __init__(self, *args, **kwargs):
        Widget.__init__(self, *args, **kwargs)
        self.rect_pos_x = 500
        self.rect_pos_y = 250
        self.rect_pos = self.rect_pos_x, self.rect_pos_y
        self.rect_width = 150
        self.rect_height = 30
        self.rect_size = self.rect_width, self.rect_height
        self.rotate_origin_x = self.rect_pos_x + self.rect_width / 2
        self.rotate_origin_y = self.rect_pos_y + self.rect_height / 2
        self.rotate_origin = self.rotate_origin_x, self.rotate_origin_y
        self.angle = 135
        print('rect 2')
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(1,255,0))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def rotate(self):
        self.canvas.clear()
        self.angle += 90
        if (self.angle > 315):
            self.angle = 225
        with self.canvas:
            Rotate(origin=self.rotate_origin, angle=self.angle)
            Color(rgb=(0, 255, 100))
            Rectangle(pos=self.rect_pos, size=self.rect_size)

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            self.rotate()
            print(self.angle)

class Stage_2(Widget):
    object2 = ObjectProperty(None)
    object3 = ObjectProperty(None)

class Manager(ScreenManager):
    pass

sm = Manager()

class ScreensApp(App):
    def build(self):
        return sm

if __name__ == '__main__':
    ScreensApp().run()

【问题讨论】:

  • 您的on_touch_up() 方法使用的是collide_point(),它将触摸点与Widget possize 进行比较,而不是Rectangle
  • 感谢@JohnAnderson 的帮助,但这可能不是问题所在,即使在单击矩形之前,第二个矩形的位置也不是应该的......请运行代码一次,如果你能看到什么输出是因为它真的很难讨论这个问题......但就问题而言,我认为它与画布有关......谢谢你......请帮助我出去!
  • 我已经运行了你的代码,我相信你使用collide_point的问题。还。你应该把PushMatrix()放在你的Canvas指令的开头,把PopMatrix()放在最后。

标签: python python-3.x kivy kivy-language


【解决方案1】:

如果您在canvas 指令中包含PushMatrix()PopMatrix(),则只有当前的Widget 会受到影响。然后,如果你将Widgetsizepos 调整为Rectangle,你应该会变得更好(但不是完美)collide_point 性能:

    with self.canvas:
        PushMatrix()
        Rotate(origin=self.rotate_origin, angle=self.angle)
        Color(rgb=(1,255,0))
        Rectangle(pos=self.rect_pos, size=self.rect_size)
        PopMatrix()
        self.pos = self.rect_pos
        self.size = self.rect_size

每当您使用涉及RotationScaleTranslatewith self.canvas 时,都需要执行此操作。 collide_point() 仍将查看 Widget sizepos,而不是 Rectangle,但至少 Widget 和它的 Rectangle 的中心应该重合。

【讨论】:

  • 太棒了!...非常感谢@JohnAnderson ...你刚刚做到了!我真的很感谢你......继续这样的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多