Kivy:如何停止重叠标签标题的散点图小部件

时间:2018-03-08 16:50:32

标签: python kivy scatter

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())

2 个答案:

答案 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对象留在标签后面。