Scatter小部件位于TabbedPanelItem内容中。移动分散对象时,它会移动所有选项卡标题。如何确保它在标签标题下移动?我得到的小部件深度索引遵循添加小部件时的顺序,但是不明白我如何在Tab小部件之前添加Scatter来避免这种情况?
问题图片:
分散小部件重叠标签标题
说明问题的代码(分散项目为红色,在标签1上):
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.base import runTouchApp
Builder.load_string("""
<TabbedTestScreen>:
TabbedPanel:
id: tab_panel
do_default_tab: False
tab_pos: 'left_top'
tab_height: 90
tab_width: 90
TabbedPanelItem:
text: '1'
BoxLayout:
size: self.size
pos: self.pos
Scatter:
canvas.after:
Color:
rgba: 1,0,0,0.5
Rectangle:
size: self.size
pos: self.pos
auto_bring_to_front: False # this doesn't make any difference
center: self.parent.center
size: self.parent.size
do_rotation: False
do_translation: True
do_scale: True
Label:
text: 'Tab 1 scatter widget'
font_size: 20
center: self.parent.center
size: self.parent.size
TabbedPanelItem:
text: '2'
Label:
text: '2'
TabbedPanelItem:
text: '3'
id: home_tab
Label:
text: '3'
""")
class TabbedTestScreen(Screen):
def __init__(self, **kwargs):
super(TabbedTestScreen, self).__init__(**kwargs)
runTouchApp(TabbedTestScreen())
答案 0 :(得分:1)
我认为这个问题与小部件订购有关。
Kivy使用窗口小部件插入到树中的顺序作为z-index,(您始终在顶部&#34;默认情况下添加&#34;)布局和复杂窗口小部件也使用此顺序作为位置的指示,大部分时间这都是好的和好的,但有时它不是,然后你有时候你需要奇怪的解决方法。
发生在这里,TabbedPanel做了一些魔术,标题实际上是&#34;之前&#34; (如下)容器,因为你的内容可以超出预期的区域,效果不是你所期望的。
我建议的解决方案是使用模板实际阻止内容在其位置之外绘制任何内容。
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.base import runTouchApp
Builder.load_string("""
<TabbedTestScreen>:
TabbedPanel:
id: tab_panel
do_default_tab: False
tab_pos: 'left_top'
tab_height: 90
tab_width: 90
TabbedPanelItem:
text: '1'
BoxLayout:
size: self.size
pos: self.pos
canvas.before:
StencilPush
Rectangle:
pos: self.pos
size: self.size
StencilUse
canvas.after:
StencilUnUse
Rectangle:
pos: self.pos
size: self.size
StencilPop
Scatter:
canvas.after:
Color:
rgba: 1,0,0,0.5
Rectangle:
size: self.size
pos: self.pos
auto_bring_to_front: False # this doesn't make any difference
center: self.parent.center
size: self.parent.size
do_rotation: False
do_translation: True
do_scale: True
Label:
text: 'Tab 1 scatter widget'
font_size: 20
center: self.parent.width / 2, self.parent.height / 2
size: self.parent.size
TabbedPanelItem:
text: '2'
Label:
text: '2'
TabbedPanelItem:
text: '3'
id: home_tab
Label:
text: '3'
""")
class TabbedTestScreen(Screen):
def __init__(self, **kwargs):
super(TabbedTestScreen, self).__init__(**kwargs)
runTouchApp(TabbedTestScreen())
但是你仍然遇到问题,虽然它在相关位置上无法正常显示,但分散仍处于活动状态且可以被抓取,这会导致界面混乱。
所以你也希望BoxLayout不要关心其位置之外的接触。
可以假设像StencilView这样的东西可以做到这一点,但它没有,所以你需要做一些工作。
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.base import runTouchApp
from kivy.uix.stencilview import StencilView
from kivy.uix.boxlayout import BoxLayout
class StencilBox(StencilView, BoxLayout):
def on_touch_down(self, touch):
if not self.collide_point(*touch.pos):
return
return super(StencilBox, self).on_touch_down(touch)
def on_touch_move(self, touch):
if not self.collide_point(*touch.pos):
return
return super(StencilBox, self).on_touch_move(touch)
def on_touch_up(self, touch):
if not self.collide_point(*touch.pos):
return
return super(StencilBox, self).on_touch_up(touch)
Builder.load_string("""
<TabbedTestScreen>:
TabbedPanel:
id: tab_panel
do_default_tab: False
tab_pos: 'left_top'
tab_height: 90
tab_width: 90
TabbedPanelItem:
text: '1'
StencilBox:
size: self.size
pos: self.pos
Scatter:
canvas.after:
Color:
rgba: 1,0,0,0.5
Rectangle:
size: self.size
pos: self.pos
auto_bring_to_front: False # this doesn't make any difference
center: self.parent.center
size: self.parent.size
do_rotation: False
do_translation: True
do_scale: True
Label:
text: 'Tab 1 scatter widget'
font_size: 20
center: self.parent.width / 2, self.parent.height / 2
size: self.parent.size
TabbedPanelItem:
text: '2'
Label:
text: '2'
TabbedPanelItem:
text: '3'
id: home_tab
Label:
text: '3'
""")
class TabbedTestScreen(Screen):
def __init__(self, **kwargs):
super(TabbedTestScreen, self).__init__(**kwargs)
runTouchApp(TabbedTestScreen())
(我还修复了一个小问题,标签位置不是相对的,因为你处于散射状态,你需要使用相对于散射的坐标,而不是整个屏幕。)
希望这有帮助。
答案 1 :(得分:0)
不是一个完整的答案,但也许是一个能够进一步发展的人的开始。如果您使用自定义Scatter
,请执行以下操作:
class MyScatter(Scatter):
def on_pos(self, *args):
parent = self.parent
gparent = parent.parent
if gparent is None:
return
ggparent = gparent.parent
if ggparent is None:
return
num_children = len(ggparent.children)
ggparent.remove_widget(gparent)
ggparent.add_widget(gparent, num_children)
非常难看,并且有副作用,我不明白(标签出现在右侧)。但是MyScatter
对象留在标签后面。