Kivy的问题-滚动视图与其上方的框布局重叠 [英] Problem with Kivy - Scrollview overlapping with Box Layout above it

查看:138
本文介绍了Kivy的问题-滚动视图与其上方的框布局重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即使在垂直Scrollview中有一个Button,我也会在顶部的固定菜单中单击该按钮,但它不会影响固定菜单.

I'm clicking the button in the fixed menu at the top even though there is a Button in the vertical Scrollview, it doesn't effect the fixed menu.

我试图单击顶部固定菜单中的按钮,但操作将发送到下面的水平Scrollview中.

I'm trying to click at the button in the fixed menu at the top but the actions are being sent to the horizontal Scrollview below.

我是使用kivy甚至是编程的新手,并且正在使用Python 3.7和Kivy(1.11.1)创建一个看起来像Netflix的Page布局的应用程序,其中在顶部和底部固定有一个菜单它有一个垂直的Scrollview,里面有一些水平的滚动视图(就像Netlix的目录一样,例如:我的列表",继续观看",系列"等).问题是,当我向下滚动垂直ScrollView并且水平滚动视图之一位于顶部的固定菜单之后时,事件将发送到该水平滚动视图,而不是滚动视图内容上方的固定菜单.如果我向下滚动垂直Scrollview,并且其中一个水平滚动视图落后"(用引号引起,因为我认为它们不应该相互碰撞),则位于顶部菜单,如果我单击菜单,则该事件正在发送到水平滚动视图.

I'm new with kivy and even programming and I'm creating an app with Python 3.7, and Kivy(1.11.1) that kinda looks like Netflix's Page layout, in which there is a menu fixed at the top and below it there is a vertical Scrollview with some horizontal scrollviews inside (just like the Netlix's catalogues, eg.: My List, Continue Watching, Series, etc). The problem is that when I scroll down the vertical ScrollView and one of the horizontal scrollview gets behind the fixed menu at the top, the events are sent to this horizontal scrollview and not to the fixed menu that is be above the Scrollview content. If I scroll the vertical Scrollview down and one of the horizontal scrollviews gets "behind" (in quotes because I imagine they aren't supposed to collide with each other) the menu at the top, if I click in the menu the event is being sent to the horizontal scrollview.

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView

Builder.load_string(
'''
<ScrollApp>:
    orientation: 'vertical'
    BoxLayout:
        size_hint: 1, 0.12
        Button:
            text: 'Fixed Menu'
            on_press: print('This button stops working if there is a horizontal scrollview "behind"')

    ScrollView:
        bar_width: 10
        scroll_type: ['bars', 'content']
        BoxLayout:
            orientation: 'vertical'
            size_hint: 1, None
            height: self.minimum_height
            padding: 22, 0, 22, 50
            spacing: 50
            canvas:
                Color:
                    rgba: .15, .15, .15, .9
                Rectangle:
                    size: self.size
                    pos: self.pos
            Button:
                size_hint: None, None
                width: 100
                height: 100
                on_press: print('This button does not overlap the menu above')

            # "ScrollViews containers"
            Custom
            Custom
            Custom
            Custom
            Custom
    BoxLayout:  
        size_hint: 1, 0.12
        Button:
            on_press: print("This menu at the bottom is not affected by the problem that occurs with the top one")


<Custom@BoxLayout>:
    orientation: 'vertical'
    size_hint: 1, None
    height: self.minimum_height
    Label:
        size_hint: None, None
        size: self.texture_size
        id: label
        font_size: 20
        text: 'Teste'
    ScrollView:
        do_scroll: True, True
        size_hint: 1, None
        height: 150
        GridLayout:
            id: grid
            size_hint: None, 1.01
            width: self.minimum_width
            spacing: 5
            cols: 3
            Button:
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
            Button:
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
            Button:
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
''' )

class ScrollApp(BoxLayout):
    pass

class Test(App):
    def build(self):
        return ScrollApp()

Test().run()


推荐答案

您确实设法在奇异果中发现了晦涩的情况:-).

You do manage to find obscure situations in kivy :-).

我相信这里的问题是触摸事件处理的顺序.触摸事件通常由顶级窗口小部件处理,并且将事件一直分配给其子级,直到Widget树.在具有多个子代的任何Widget中,touch事件均以与添加到其父代的相反顺序分派给子代.并且在kv中,子Widgets按其出现的顺序添加(从上到下).因此,在您的情况下,ScrollApp有三个子级,触摸事件将从包含底部菜单的BoxLayout开始分派给其子级,然后分派给ScrollView,最后分派给,其中包含顶部菜单.因此,ScrollView在顶部菜单之前获取touch事件,并将触摸分配给它的子级(包括Custom实例).因此,Custom中的Buttons会在顶部菜单看到触摸事件之前先看到触摸事件,然后他们将其声明为自己的事件.解决该问题的明显方法是更改​​ScrollApp中出现的Widgets的顺序,但是由于ScrollAppBoxLayout,因此将大大改变App的外观.另一种解决方法是使用不依赖于其子顺序的Layout. FloatLayout之类的东西具有这种特征.因此,这是代码的修改版本,使ScrollApp扩展FloatLayout而不是BoxLayout:

I believe the problem here is the order of touch event processing. The touch events are normally processed by the top level widgets, and they dispatch the event to their children, all the way down the Widget tree. In any Widget with multiple children, the touch event is dispatched to children in the reverse order that they have been add to their parent. And in kv, child Widgets are added in order as they appear (top to bottom). So, in your case, the ScrollApp has three children, and the touch events will be dispatched to its children starting with the BoxLayout that contains the bottom menu, then to the ScrollView, and lastly, to the BoxLayout that contains the top menu. So the ScrollView gets the touch event before the top menu, and dispatches the touch to its children (including the Custom instances). So the Buttons in the Custom see the touch event before the top menu sees it, and they claim it as their own. The obvious way to fix it would be to change the order of Widgets that appear in the ScrollApp, but since ScrollApp is a BoxLayout, that would dramatically change how your App looks. A different fix is to use a Layout that doesn't depend on the order of its children. Something like a FloatLayout has that characteristic. So, here is a modified version of your code, that makes ScrollApp extend FloatLayout instead of BoxLayout:

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout

Builder.load_string(
'''
<ScrollApp>:
    ScrollView:
        size_hint: 1.0, 0.76
        pos_hint: {'center_y':0.5}
        bar_width: 10
        scroll_type: ['bars', 'content']
        BoxLayout:
            orientation: 'vertical'
            size_hint: 1, None
            height: self.minimum_height
            padding: 22, 0, 22, 50
            spacing: 50
            canvas:
                Color:
                    rgba: .15, .15, .15, .9
                Rectangle:
                    size: self.size
                    pos: self.pos
            Button:
                size_hint: None, None
                width: 100
                height: 100
                on_press: print('This button does not overlap the menu above')

            # "ScrollViews containers"
            Custom
            Custom
            Custom
            Custom
            Custom
    BoxLayout:  
        size_hint: 1, 0.12
        pos_hint: {'y':0}
        Button:
            on_press: print("This menu at the bottom is not affected by the problem that occurs with the top one")
    BoxLayout:
        size_hint: 1, 0.12
        pos_hint: {'top':1.0}
        Button:
            text: 'Fixed Menu'
            on_press: print('This button stops working if there is a horizontal scrollview "behind"')


<Custom@BoxLayout>:
    orientation: 'vertical'
    size_hint: 1, None
    height: self.minimum_height
    Label:
        size_hint: None, None
        size: self.texture_size
        id: label
        font_size: 20
        text: 'Teste'
    ScrollView:
        do_scroll: True, True
        size_hint: 1, None
        height: 150
        GridLayout:
            id: grid
            size_hint: None, 1.01
            width: self.minimum_width
            spacing: 5
            cols: 3
            Button:
                text: 'button 1'
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
            Button:
                text: 'button 2'
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
            Button:
                text: 'button 3'
                size_hint: None, None
                size: 400, 150
                on_press: print('ScrollView button pressed')
''' )


class ScrollApp(FloatLayout):
    pass


class Test(App):
    def build(self):
        return ScrollApp()

Test().run()

因此,通过ScrollApp中的此子顺序,顶部菜单和底部菜单会在ScrollView之前的触摸事件中得到显示.

So, with this child order in ScrollApp, the top and bottom menus get their shot at the touch events before the ScrollView.

我实际上认为您的代码无需进行此更改即可工作,因此可能发生了其他我找不到的事情.

I actually think your code should work without this change, so there may be something else happening that I couldn't find.

这篇关于Kivy的问题-滚动视图与其上方的框布局重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆