Kivy:GridLayout 中的按钮有间隙

Posted

技术标签:

【中文标题】Kivy:GridLayout 中的按钮有间隙【英文标题】:Kivy: Buttons in GridLayout have gap 【发布时间】:2019-12-14 10:25:21 【问题描述】:

在 GridLayout 内部,奇数 Button 子级不会出现。

我已经尝试了 Button 和 GridLayout 大小、size_hint、高度等的几种配置,但似乎无法解决这个问题。从子项中删除 Button 类可以解决此问题,但我想要按钮小部件的功能。

main.py:

from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import NumericProperty, StringProperty, ListProperty
from kivy.uix.behaviors.focus import FocusBehavior
from kivy.uix.button import Button


class Tube(Button, RelativeLayout, FocusBehavior):
    pass


class TubeMapView(GridLayout, FocusBehavior):
    orderNumber = NumericProperty()
    customerName = StringProperty("")
    tubeList = ListProperty([])
    bundleList = ListProperty([])

    def add_tube(self):
        self.tubeList.append(Tube())
        self.add_widget(self.tubeList[-1])

    def _on_focusable(self, instance, value):
        self.add_tube()

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        print(keycode)
        if keycode[1] is 'enter':
            self.add_tube()




class LengthView(GridLayout):
    pass


class AppView(GridLayout):
    pass


class TubeMapApp(App):
    pass


if __name__ == '__main__':
    TubeMapApp().run()

tubemap.kv:

<Tube>:
    size_hint_y: None
    height: dp(60)
    canvas.before:
        Color:
            rgba: (0,1,0,1)
        Rectangle:
            size: self.size

<LengthView>:
    size_hint_x: 1
    size_hint_y: 1

    canvas.before:
        Color:
            rgba: (0,0,1,1)
        Rectangle:
            size: self.size


<TubeMapView>:
    cols: 1
    rows: None
    size_hint_max_x:
    size_hint_y: None
    height: self.minimum_height
    canvas.before:
        Color:
            rgba: (0,1,0,1)
        Rectangle:
            pos: self.pos
            size: self.size


AppView:
    cols: 2
    rows: None
    RelativeLayout:
        size_hint_x: 0.75
        ScrollView:
            size: self.size
            TubeMapView:
                focus: True
                Tube:
                Tube:
                Tube:
    RelativeLayout:
        size_hint_x: 0.25
        ScrollView:
            LengthView:

我希望每个 Button 都会渲染,但只有其他 Button 才会渲染,从第一个开始:

【问题讨论】:

你真的需要你的Tube类来扩展RelativeLayout吗? 不,但是随着我将更多标签和其他元素附加到 Tube 类,RelativeLayout 将更容易管理,并且将来会减少混乱。关于为什么 RelativeLayout 产生这种行为的任何想法? 【参考方案1】:

您可以继承 Button、RelativeLayout 和 FocusBehavior,并创建自己的样式。

片段 - py 文件

class Tube(Button, RelativeLayout, FocusBehavior):
    pass

片段 - kv fie

<-Tube>:
    text: ''
    focus: False

    size_hint_y: None
    height: dp(60)

    canvas.before:
        Color:
            rgba: (0,1,0,1)
            # rgba: (1,0,1,0.5) if self.focus else (0,1,0,1)
        Rectangle:
            size: self.size

    state_image: self.background_normal if self.state == 'normal' else self.background_down
    disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down

    canvas:
        Color:
            rgba: (1,0,1,1) if self.focus else self.background_color
        BorderImage:
            border: self.border
            pos: self.pos
            size: self.size
            source: self.disabled_image if self.disabled else self.state_image
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            texture: self.texture
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)

输出

示例

下面的kv文件是一个模型。

poc.kv

<-Tube>:
    text: ''
    focus: False
    size_hint_y: None
    height: dp(60)
    canvas.before:
        Color:
            rgba: (0,1,0,1)
        Rectangle:
            size: self.size

    state_image: self.background_normal if self.state == 'normal' else self.background_down
    disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down

    canvas:
        Color:
            rgba: (1,0,1,1) if self.focus else self.background_color
        BorderImage:
            border: self.border
            pos: self.pos
            size: self.size
            source: self.disabled_image if self.disabled else self.state_image
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            texture: self.texture
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)

<LengthView>:
    size_hint_x: 1
    size_hint_y: 1

    canvas.before:
        Color:
            rgba: (0,0,1,1)
        Rectangle:
            size: self.size


<TubeMapView>:
    cols: 1
    rows: None
    size_hint_y: None
    height: self.minimum_height
    canvas.before:
        Color:
            rgba: (0,1,0,1)
        Rectangle:
            pos: self.pos
            size: self.size


AppView:
    cols: 2
    rows: None
    RelativeLayout:
        size_hint_x: 0.75
        ScrollView:
            size: self.size
            TubeMapView:
                Tube:
                    focus: True
                    text: 'tube 1'
                Tube:
                    text: 'tube 2'
                Tube:
                    text: 'tube 3'

    RelativeLayout:
        size_hint_x: 0.25
        ScrollView:
            LengthView:

【讨论】:

这个例子正确地解决了这个问题。但是,我仍然不明白为什么会发生这种行为,这在 Kivy 中经常发生。对此有什么想法吗?【参考方案2】:

如果您希望您的 Tube 成为行为类似于 ButtonRelativeLayout,请将您的 Tube 类的声明更改为:

class Tube(ButtonBehavior, FocusBehavior, RelativeLayout):
    pass

请注意,documentation 表示 Behavior 类在继承中必须位于 Widget 类之前。

此更改符合我的想法。

【讨论】:

以上是关于Kivy:GridLayout 中的按钮有间隙的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kivy Python 中为 GridLayout 的某些按钮设置高度?

MDRectangleFlatButton(s) 不采用它们在 GridLayout 或 MDGridLayout 中应该具有的大小。 Kivy 的按钮工作正常

如何使用 kv 文件刷新 Kivy 中的 GridLayout

标签上gridlayout内的kivy滚动视图

如何在其他屏幕kivy中显示情节

用图像填充 Python 的 Kivy 中的 GridLayout