Использование идентификаторов для изменения свойств виджетов в Киви

#python #oop #kivy #kivy-language

Вопрос:

Я недавно начал работать над проектом в Киви, чтобы лучше понять библиотеку. Я дошел до определенного момента настройки главного экрана, когда у меня начались проблемы с управлением идентификаторами из моего сценария kv в моем коде python.

Подводя итог, я в настоящее время работаю над кодом, который заставит мой плеер (ресурсы/player1.png) указывать на курсор. Чтобы определить положение курсора, я использую сенсорный виджет и печатаю координаты при нажатии. Затем я хочу передать эту информацию в функцию, которая примет ее и соответствующим образом повернет изображение (я знаю, что мне еще предстоит поработать в этой области). Однако, когда я пытаюсь получить идентификатор изображения (идентификатор: плеер) для поворота, я в конечном итоге получаю KeyError: 'player' . Я попытался перечислить идентификаторы, напечатав self.id, но ни один из них не указан, как видно на выходных данных (пустые фигурные скобки перед сообщениями об ошибках). Я искал эту ошибку и просмотрел документы Киви по идентификаторам, но ничего не нашел.

Вот код, который у меня есть в настоящее время:

 from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget


class Window1(Screen):
    pass

class Window2(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class Touch(Widget):
    def aim(self):
        print(self.ids)
        player_id = self.ids['player']
        player_id.rotate(90.0, 0.0, 0.0, 0.0)

    def on_touch_down(self, touch):
        print(touch)
        self.aim()
 

Файл Kv:

 #: import NoTransition kivy.uix.screenmanager.SlideTransition

WindowManager:
    Window1:
    Window2:

<Window1>:
    id: win1
    name: 'w1'

    RelativeLayout:
        orientation: 'vertical'
        size: root.width, root.height

        Label:
            text: 'TITLE'
            font_size: 40
            size_hint: .3, .2
            pos_hint: {'top': 0.7, 'right': 2/3}
        Button:
            size_hint: .3, .2
            pos_hint: {'top': 0.5, 'right': 2/3}
            text: 'START'
            font_size: 40
            on_release:
                app.root.transition = NoTransition(duration=0)
                app.root.current = 'w2'


<Window2>:
    id: win2
    name: 'w2'
    Touch:
        canvas.before:
            Color:
                rgb: (.1, .1, .1)
            Rectangle:
                size: self.size
        canvas:

            Color:
                rgb: (1, 1, 1)
            Rectangle:
                id: player
                source: 'resources/player1.png'
                size: 66, 99
                pos: (self.width/2-33, self.height/2-49.5)
 

Выход:

 [INFO   ] [Logger      ] Record log in C:Usersdaqna.kivylogskivy_21-10-11_31.txt
[INFO   ] [deps        ] Successfully imported "kivy_deps.angle" 0.3.0
[INFO   ] [deps        ] Successfully imported "kivy_deps.glew" 0.3.0
[INFO   ] [deps        ] Successfully imported "kivy_deps.sdl2" 0.3.1
[INFO   ] [Kivy        ] v2.0.0
[INFO   ] [Kivy        ] Installed at "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivy__init__.py"
[INFO   ] [Python      ] v3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)]
[INFO   ] [Python      ] Interpreter at "C:UsersdaqnaPycharmProjectsgamevenvScriptspython.exe"
[INFO   ] [Factory     ] 186 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2 (img_pil, img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.6.0 - Build 30.0.100.9922'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Intel(R) UHD Graphics'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60 - Build 30.0.100.9922'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [GL          ] NPOT texture support is available
[INFO   ] [Base        ] Start application main loop
<MouseMotionEvent spos=(0.71625, 0.43666666666666665) pos=(573.0, 262.0)>
{}
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "C:UsersdaqnaPycharmProjectsgamemain.py", line 35, in <module>
     GameApp().run()
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivyapp.py", line 950, in run
     runTouchApp()
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivybase.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivybase.py", line 347, in mainloop
     self.idle()
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivybase.py", line 391, in idle
     self.dispatch_input()
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivybase.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivybase.py", line 248, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivycorewindow__init__.py", line 1412, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivycorewindow__init__.py", line 1428, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivyuixscreenmanager.py", line 1198, in on_touch_down
     return super(ScreenManager, self).on_touch_down(touch)
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivyuixwidget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivyuixrelativelayout.py", line 297, in on_touch_down
     ret = super(RelativeLayout, self).on_touch_down(touch)
   File "C:UsersdaqnaPycharmProjectsgamevenvlibsite-packageskivyuixwidget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:UsersdaqnaPycharmProjectsgamemain.py", line 24, in on_touch_down
     self.aim()
   File "C:UsersdaqnaPycharmProjectsgamemain.py", line 19, in aim
     player_id = self.ids['player']
 KeyError: 'player'

Process finished with exit code 1
 

Извините, если есть действительно очевидное решение, я новичок в киви и не очень хорошо понимаю идентификаторы и, честно говоря, ООП. Спасибо за отзыв.

Ответ №1:

К сожалению, вы не можете назначить id инструкцию для холста. Другой подход заключается в том, чтобы просто Touch расширить Image и повернуть весь виджет. Для этого измените свой kv для <Window2> :

 <Window2>:
    id: win2
    name: 'w2'
    Touch:
        id: player
        source: 'resources/player1.png'
        size_hint: None, None
        size: 66, 99
        pos: (root.width/2-33, root.height/2-49.5)

        canvas.before:
            PushMatrix
            Rotate:
                angle: self.rotate
                axis: 0,0,1
                origin: self.center
        canvas.after:
            PopMatrix
 

И измените Touch виджет следующим образом:

 class Touch(Image):
    rotate = NumericProperty(0)  # the angle for rotating the Image

    def aim(self):
        self.rotate  = 90.0

    def on_touch_down(self, touch):
        print(touch)
        self.aim()