在网格单元格中定位小部件?

Positioning widgets in a grid cell?

我正在尝试定位动态添加到网格的标签。我希望第二列中的标签小部件全部对齐到列的右侧而不是左侧。我试过各种对齐方式都无济于事。所以我把它缩减为这个演示代码在这个阶段我想知道我是否可以将标签宽度绑定到列宽并且 然后 使用对齐。或者我可以覆盖标签的 on_size 并将其调整为父网格列吗?

代码

import kivy
kivy.require('2.1.0')

from kivy.app            import App
from kivy.uix.label      import Label
from kivy.uix.gridlayout import GridLayout
from kivy.factory        import Factory

class AlignTestGridLayout(GridLayout):

    def __init__(self, **kwargs):
        super(AlignTestGridLayout, self).__init__(**kwargs)

    def update( self, *args):
        for j in range(0,4):
            for i in range(0,4):
                newCell = Factory.GridEntry()
                newCell.text = 'text' + ( str(j) * (j + 1))
                self.ids.gridCalendar.add_widget( newCell )

class AlignTestApp(App):

    def build(self):
        AlignTest = AlignTestGridLayout()
        AlignTest.update()
        return AlignTest

if __name__ == '__main__':

    AlignTestApp().run()

KV

#:kivy 2.1.0

<Widget>:
    # draw outlines for debugging only
    canvas.after:
        Line:
            rectangle: self.x+1,self.y+1,self.width-1,self.height-1
            dash_offset: 5
            dash_length: 3

<GridEntry@Label>:
    padding_x: 5
    font_size: 25
    size_hint: (None, None)
    size: self.texture_size

<AlignTestGridLayout>:
    GridLayout:
        id: gridCalendar
        cols: 4
        rows: 4
        size: self.minimum_size

您不能使子项的大小取决于列宽,也不能对 GridLayout 使用 minimum_size。你可以看到它会导致无限循环。

此外,您发布的代码应该打印一条警告,说明未为 AlignTestGridLayout 设置 rowscols(即使它们是为子 GridLayout).

因此,一些更改允许 GridEntry 填充其网格单元格并使用 halign 进行定位。这是您的 kv 的修改版本:

<Widget>:
    # draw outlines for debugging only
    canvas.after:
        Line:
            rectangle: self.x+1,self.y+1,self.width-1,self.height-1
            dash_offset: 5
            dash_length: 3

<GridEntry@Label>:
    col: 0  # the column number for this GridEntry
    padding_x: 5
    font_size: 25
    # size_hint: (None, None)
    # size: self.texture_size  # allow entry to fill the grid cell
    text_size: self.size
    halign: 'right' if self.col == 1 else 'left'  # alignment based on column number

<AlignTestGridLayout>:
    cols: 1  # at least cols or rows should be defined
    size_hint: 0.75, 0.75  # control size of grid here
    GridLayout:
        id: gridCalendar
        cols: 4
        rows: 4
        # size: self.minimum_size  # cannot use minimum_size unless sizes of children are specified explicitly

并稍作改动以向 GridEntry 提供列号:

class AlignTestGridLayout(GridLayout):
    def update( self, *args):
        for j in range(0,4):
            for i in range(0,4):
                newCell = Factory.GridEntry()
                newCell.col = i  # set column number for this newCell
                newCell.text = 'text' + ( str(j) * (j + 1))
                self.ids.gridCalendar.add_widget( newCell )

您可以使用 Labelhalign 属性 来定位它的 text 但是当它的大小绑定到它的 texture_size 时这不起作用.所以为了使用那个 属性 你可以只绑定它的 height 到它的纹理高度并修改它的 text_size.

同样,在这种情况下,您可以使用 minimum_height 限制其父级布局(此处 GridLayout)的高度(也可以限制 width,您可以明确指定或使用 col_default_width等)。

有了所有这些,您在 kvlang 中修改后的代码现在看起来像,

#:kivy 2.1.0

<Widget>:
    # draw outlines for debugging only
    canvas.after:
        Line:
            rectangle: self.x+1,self.y+1,self.width-1,self.height-1
            dash_offset: 5
            dash_length: 3

<GridEntry@Label>:
    padding_x: 5
    font_size: 25
    size_hint_y: None
    height: self.texture_size[1]
    text_size: self.width, None

<AlignTestGridLayout>:
    cols: 1  # You must provide a value to at least one of `cols` and `rows`.
    GridLayout:
        id: gridCalendar
        cols: 4
        rows: 4
        size_hint_y: None
        height: self.minimum_height

现在要更改标签在特定列中的位置,您可以将逻辑修改为,

    def update( self, *args):
        for j in range(0,4):
            for i in range(0,4):
                newCell = Factory.GridEntry()
                newCell.halign = "right" if i == 1 else "left"
                newCell.text = 'text' + ( str(j) * (j + 1))
                self.ids.gridCalendar.add_widget( newCell )