Kivy:旋转可点击的图像

时间:2016-05-01 18:52:47

标签: python kivy

我创建了一个可点击的图片,我可以旋转它,但我无法获得正确的旋转原点。以下代码将两个图像(其中一个可单击)放置到表单上。我希望它们在彼此之上,可点击的一个旋转。可点击的一个旋转,但旋转原点是图像中心以外的其他东西导致它被移动,即使我指定中心是我期望的。有趣的是,它是可点击的,但点击区域应该是:在不可点击的图像上。也就是说,单击蓝色图像时红色图像变为绿色!

我从网上找到的一些kv语言修改了这段代码,并且轮换工作正常。但我需要以编程方式设置按钮,因为我最终会有一个包含许多的表单,每个表单都会以不同的方式旋转和移动。

我觉得问题在于坐标单位不匹配,但我在网上和文档中找不到多少。任何帮助表示赞赏。图像只有32x32图标,您可以用任何方便的图标替换它们。

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics.context_instructions import PopMatrix, PushMatrix
from kivy.graphics import Rotate
from kivy.uix.behaviors import ButtonBehavior

h = .05
w = h * 1.6

class IconButton(ButtonBehavior, Image):

    def __init__(self, angle=0, **kwargs):
        super(IconButton, self).__init__(**kwargs)

        self.canvas.before.add(PushMatrix())
        self.canvas.before.add(Rotate(angle = angle, origin = [self.get_center_x(), self.get_center_y()]))

        self.canvas.after.add(PopMatrix())

    def on_press(event):
        event.source = event.img_dn
        print '{} pressed'.format(event.id)

    def on_release(event):
        event.source = event.img_up
        print '{} released'.format(event.id)


class TestApp(App):

    def build(self):
        layout = FloatLayout()
        btn = IconButton(angle=-20, id='b1', size_hint=(h,w), pos_hint = {'center_x': .25, 'center_y': .9})
        btn.img_up = 'loudspeaker_red_32.png'
        btn.img_dn = 'loudspeaker_green_32.png'
        btn.source = btn.img_up

        layout.add_widget(btn)

        im = Image(id='i1', size_hint=(h,w), pos_hint = {'center_x': .25, 'center_y': .9})
        im.source = 'loudspeaker_blue_32.png'

        layout.add_widget(im)

        return layout

class MainApp(App):
    def build(self):
        layout = Builder.load_string(src)
        return layout


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

1 个答案:

答案 0 :(得分:2)

如果您尝试在窗口小部件周围绘制一条线(一种非常有用的调试技术),您会发现在IconButton.__init__()被调用时pos属性仍然是(0, 0)并且代码认为您的按钮位于左下角。

class IconButton(ButtonBehavior, Image):

    def __init__(self, angle=0, **kwargs):
        super(IconButton, self).__init__(**kwargs)

        self.canvas.before.add(PushMatrix())

        self.canvas.add(Color(rgba=(1,0,0,.5)))
        self.canvas.add(Line(rectangle=(self.x, self.y, self.width, self.height)))

        self.canvas.after.add(PopMatrix())

    def on_press(event):
        event.source = event.img_dn
        print '{} pressed'.format(event.id)

    def on_release(event):
        event.source = event.img_up
        print '{} released'.format(event.id)

当您的窗口小部件放置在布局中时,会发生这种情况。pos属性已实现。当您创建Widget时,它不知道它将被放置在何处。这就是为什么你需要在以后调用的on_pos方法中实现旋转原点,当所有属性设置正确时:

class IconButton(ButtonBehavior, Image):

    def __init__(self, angle=0, **kwargs):
        super(IconButton, self).__init__(**kwargs)

        self.rotate = Rotate(angle = angle)

        self.canvas.before.add(PushMatrix())
        self.canvas.before.add(self.rotate)
        self.canvas.after.add(PopMatrix())

        self.bind(pos=self.update_canvas)
        self.bind(size=self.update_canvas)

    def update_canvas(self, *args):
        self.rotate.origin = self.center         

    def on_press(event):
        event.source = event.img_dn
        print '{} pressed'.format(event.id)

    def on_release(event):
        event.source = event.img_up
        print '{} released'.format(event.id)

这种不便使我们更倾向于使用.kv语言来描述布局。