【问题标题】:Problem with Kivy - Scrollview overlapping with Box Layout above itKivy 的问题 - 滚动视图与上方的框布局重叠
【发布时间】:2019-08-08 16:51:21
【问题描述】:

我点击顶部固定菜单中的按钮,即使垂直滚动视图中有一个按钮,它也不会影响固定菜单。

我正在尝试单击顶部固定菜单中的按钮,但操作正在发送到下面的水平滚动视图。

我是 kivy 甚至编程的新手,我正在使用 Python 3.7 和 Kivy(1.11.1) 创建一个应用程序,这有点像 Netflix 的页面布局,其中有一个固定在顶部和底部的菜单它有一个垂直滚动视图,里面有一些水平滚动视图(就像 Netlix 的目录,例如:我的列表、继续观看、系列等)。问题是,当我向下滚动垂直 ScrollView 并且水平滚动视图之一位于顶部的固定菜单后面时,事件将发送到此水平滚动视图而不是滚动视图内容上方的固定菜单。如果我向下滚动垂直 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()


【问题讨论】:

    标签: python kivy scrollview kivy-language


    【解决方案1】:

    你确实设法在 kivy 中找到模糊的情况:-)。

    我相信这里的问题是触摸事件处理的顺序。触摸事件通常由顶级小部件处理,并且它们将事件分发给它们的孩子,一直到Widget 树。在任何具有多个子代的Widget 中,触摸事件会按照与添加到父代的相反顺序发送给子代。在kv 中,子Widgets 按出现的顺序添加(从上到下)。因此,在您的情况下,ScrollApp 有三个孩子,触摸事件将从包含底部菜单的 BoxLayout 开始分派给它的孩子,然后是 ScrollView,最后是 @987654328 @ 包含顶部菜单。因此ScrollView 在顶部菜单之前获取触摸事件,并将触摸分派给其子级(包括Custom 实例)。因此,Custom 中的 Buttons 在顶部菜单看到触摸事件之前看到它,并且他们声称它是他们自己的。解决它的明显方法是更改​​出现在ScrollApp 中的Widgets 的顺序,但由于ScrollApp 是BoxLayout,这将极大地改变App 的外观。另一种解决方法是使用不依赖于其子级顺序的Layout。像FloatLayout 这样的东西有这个特点。因此,这是您的代码的修改版本,它使 ScrollApp 扩展 FloatLayout 而不是 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 之前获得触摸事件。

    我实际上认为您的代码应该在没有此更改的情况下工作,因此可能会发生我找不到的其他事情。

    【讨论】:

    • 你救了我这么多!再次感谢你。不幸的是,Kivy 似乎有一些非常烦人的未解决错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多