Kivy 的问题 - 滚动视图与其上方的框布局重叠
Problem with Kivy - Scrollview overlapping with Box Layout above it
我点击了顶部固定菜单中的按钮,即使在垂直滚动视图中有一个按钮,它也不会影响固定菜单。
我试图点击顶部固定菜单中的按钮,但操作被发送到下方的水平滚动视图。
我是 kivy 新手,甚至是编程新手,我正在使用 Python 3.7 和 Kivy(1.11.1) 创建一个应用程序,它有点像 Netflix 的页面布局,其中有一个菜单固定在顶部和下方有一个垂直滚动视图,里面有一些水平滚动视图(就像 Netlix 的目录,例如:我的列表、继续观看、系列等)。问题是,当我向下滚动垂直滚动视图并且其中一个水平滚动视图位于顶部的固定菜单后面时,事件将发送到此水平滚动视图,而不是发送到滚动视图内容上方的固定菜单。如果我向下滚动垂直滚动视图并且其中一个水平滚动视图获得 "behind" (在引号中因为我认为它们不应该相互碰撞)顶部的菜单,如果我在菜单中单击事件正在发送到水平滚动视图。
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()
你确实设法在 kivy 中找到了模糊的情况:-)。
我认为这里的问题是触摸事件处理的顺序。触摸事件通常由顶级小部件处理,并且它们将事件分派给它们的子级,一直向下到 Widget
树。在任何具有多个子项的 Widget
中,触摸事件将按照与添加到父项的顺序相反的顺序分派给子项。在 kv
中,子 Widgets
按出现的顺序添加(从上到下)。因此,在您的情况下,ScrollApp
有三个子项,触摸事件将从包含底部菜单的 BoxLayout
开始分派给它的子项,然后分派给 ScrollView
,然后最后,到包含顶级菜单的 BoxLayout
。因此 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 新手,甚至是编程新手,我正在使用 Python 3.7 和 Kivy(1.11.1) 创建一个应用程序,它有点像 Netflix 的页面布局,其中有一个菜单固定在顶部和下方有一个垂直滚动视图,里面有一些水平滚动视图(就像 Netlix 的目录,例如:我的列表、继续观看、系列等)。问题是,当我向下滚动垂直滚动视图并且其中一个水平滚动视图位于顶部的固定菜单后面时,事件将发送到此水平滚动视图,而不是发送到滚动视图内容上方的固定菜单。如果我向下滚动垂直滚动视图并且其中一个水平滚动视图获得 "behind" (在引号中因为我认为它们不应该相互碰撞)顶部的菜单,如果我在菜单中单击事件正在发送到水平滚动视图。
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()
你确实设法在 kivy 中找到了模糊的情况:-)。
我认为这里的问题是触摸事件处理的顺序。触摸事件通常由顶级小部件处理,并且它们将事件分派给它们的子级,一直向下到 Widget
树。在任何具有多个子项的 Widget
中,触摸事件将按照与添加到父项的顺序相反的顺序分派给子项。在 kv
中,子 Widgets
按出现的顺序添加(从上到下)。因此,在您的情况下,ScrollApp
有三个子项,触摸事件将从包含底部菜单的 BoxLayout
开始分派给它的子项,然后分派给 ScrollView
,然后最后,到包含顶级菜单的 BoxLayout
。因此 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
之前的触摸事件中获得成功。
实际上我认为您的代码应该可以在没有此更改的情况下工作,因此可能发生了我找不到的其他事情。