首页 > 解决方案 > 如何在具有重叠小部件的应用程序中分离 kivy 中的触摸

问题描述

我正在制作钢琴应用程序,但无法分开触摸。只是为了说明,我使用了 KivyMD。
这是我正在使用的结构:

enter<MainScreen>:
name: 'main'  
MDFloatLayout:

    MDStackLayout:
        id: white_notes_layout
        padding: '0dp'
        spacing: '0dp'
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}

    MDFloatLayout:
        id: black_notes_layout code here

white_notes_layout 将拥有钢琴的所有白键,而 black_notes_layout 将拥有所有黑键。

下面是我用来获取按钮的代码。
white_notes = 包含白键音符的音频文件名称的列表 [共 8 个]
black_notes = 包含白键音符的音频文件名称的列表 [共 5 个]
notes_loaded = 包含使用 SoundLoader 加载的两种类型音符的声音的列表 [前 8 个white_notes 和 black_notes 的索引]

class MainScreen(MDScreen):
    def on_enter(self, *args): 
        # White Keys' generation
        for note in white_notes:
            NoteButton=Factory.MDFlatButton(size_hint=(1,0.125))
            self.ids[note]=NoteButton
            NoteButton.name=note
            NoteButton.bind(on_press=self.play_note)
            self.ids.white_notes_layout.add_widget(NoteButton)
    
        #Black Keys' generation
        count=1          #used to skip one position
        top_position=1   # used to change 'top' pos_hint of black keys in floatlayout
        note_index=0     # used to stop while loop after all black keys are inserted
        while note_index<len(black_notes):
            note=black_notes[note_index]
            if count!=3:
                top_position-=0.08
                NoteButton=Factory.MDRaisedButton(size_hint=(0.65,0.09), pos_hint={'right':1, 'top':top_position})
                NoteButton.md_bg_color=(0,0,0,1)
                NoteButton.name=note
                NoteButton.bind(on_press=self.play_note)
                self.ids.black_notes_layout.add_widget(NoteButton)
                top_position-=0.045
                count+=1
                note_index+=1
            else:
                top_position-=0.08
                top_position-=0.045
                count=0

    def on_leave(self, *args):
         self.ids.white_notes_layout.remove_widget(self.ids.white_notes_layout.children[0])

    def play_note(self, button, *args):
        note=button.name
        if note in black_notes:
            note=self.notes_loaded[black_notes.index(note)+len(white_notes)]
        elif note in white_notes:
            note=self.notes_loaded[white_notes.index(note)]
        if note:
            note.volume=note_volume
            note.play()

这是它的外观:

钢琴图像

如您所见,黑键与白键重叠。因此,当按下黑键时,也会按下白键。我尝试使用 collide_points 进行碰撞检测,但遇到了以下问题:

  1. 我尝试使用带有自定义 on_press 的自定义按钮。但我无法获得触摸位置,on_touch_down 确实有触摸位置,但我无法在 on_press 中获得它。那么我如何在 on_press 中获得“触摸”。
  2. 进行碰撞时,我需要检查该点是否在任何黑键中。所以,我需要 black_key.collide_point()。由于我为白色按钮创建了另一个类,因此我尝试使用以下方法获取黑键:
    for child in app.ids.black_notes_layout.children
    为此,我需要 python 文件中的“应用程序”。所以我做到了app = MDApp.get_running_app(),但这显示“无类型对象没有属性 ID”错误。然后我从 kivy.app 导入 App 并尝试 App.get_running_app() 但再次失败。



所以请告诉这两个问题的解决方案:
1.如何联系on_press()
2.如何获取应用程序的所有ID。
或者告诉我可以解决这个问题的替代方法。(尽可能不改变应用程序的结构)

标签: kivycollision-detectionkivymdonpress

解决方案


推荐阅读