Kivy:GridLayout总是从左到右然后向下,你能从上到下然后从左到右?

时间:2017-06-24 12:16:44

标签: python kivy kivy-language

我在Kivy的一个相对简单的布局上工作,想要显示一系列按钮从屏幕的顶部到底部填充,然后当它们到达底部时,从顶部开始一个新列

GridLayout看起来像我想要的那样,但它似乎总是先从左到右,而不是从上到下。我查看了官方文档和Google,但似乎无法找到解决方案。

StackLayout通过"方向做我想要的事情:" tb-lr"但是,当GridLayout只执行一个并且此应用程序需要的列时,按钮宽度不会完全缩放以适合容器。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

如果我没有犯错,则不会实现此功能。但是,您可以使用Layout类(kivy.uix.layout)自由地实现自己的布局。

另一种可能性是sublassify GridLayout并覆盖几个方法来从上到下添加witgets:

  

警告

     

GridLayout类在Kivy 1.9和Kivy 1.10之间有重大变化。出于这个原因,代码在 Kivy 1.10.0 上正常工作,但在以前的版本中没有(请参阅注释)。

     

您必须始终指定布局的行数

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button


def nmax(*args):
    # merge into one list
    args = [x for x in args if x is not None]
    return max(args)


def nmin(*args):
    # merge into one list
    args = [x for x in args if x is not None]
    return min(args)

class TBGridLayout(GridLayout):

    def _fill_rows_cols_sizes(self):
        cols, rows = self._cols, self._rows
        cols_sh, rows_sh = self._cols_sh, self._rows_sh
        cols_sh_min, rows_sh_min = self._cols_sh_min, self._rows_sh_min
        cols_sh_max, rows_sh_max = self._cols_sh_max, self._rows_sh_max

        # calculate minimum size for each columns and rows
        n_rows = len(rows)
        has_bound_y = has_bound_x = False
        for i, child in enumerate(reversed(self.children)):
            (shw, shh), (w, h) = child.size_hint, child.size
            shw_min, shh_min = child.size_hint_min
            shw_max, shh_max = child.size_hint_max
            col,  row = divmod(i, n_rows)

            # compute minimum size / maximum stretch needed
            if shw is None:
                cols[col] = nmax(cols[col], w)
            else:
                cols_sh[col] = nmax(cols_sh[col], shw)
                if shw_min is not None:
                    has_bound_x = True
                    cols_sh_min[col] = nmax(cols_sh_min[col], shw_min)
                if shw_max is not None:
                    has_bound_x = True
                    cols_sh_max[col] = nmin(cols_sh_max[col], shw_max)

            if shh is None:
                rows[row] = nmax(rows[row], h)
            else:
                rows_sh[row] = nmax(rows_sh[row], shh)
                if shh_min is not None:
                    has_bound_y = True
                    rows_sh_min[col] = nmax(rows_sh_min[col], shh_min)
                if shh_max is not None:
                    has_bound_y = True
                    rows_sh_max[col] = nmin(rows_sh_max[col], shh_max)
        self._has_hint_bound_x = has_bound_x
        self._has_hint_bound_y = has_bound_y

    def _iterate_layout(self, count):
        selfx = self.x
        padding_left = self.padding[0]
        padding_top = self.padding[1]
        spacing_x, spacing_y = self.spacing

        i = count - 1
        x = selfx + padding_left

        for col_width in self._cols:
            y = self.top - padding_top
            for row_height in self._rows:
                if i < 0:
                    break
                yield i, x, y - row_height, col_width, row_height
                i -=  1
                y -=  spacing_y + row_height
            x += col_width + spacing_x

# EXAMPLE OF USE    
class MainWindow(BoxLayout):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.orientation = 'vertical'
        self.layout = TBGridLayout(rows=5)
        self.add_widget(self.layout)

        self.cont = 0
        self.add_widget(Button(text='Add Button',
                               size_hint = (1,  0.15),  
                               on_press= self.add_button))


    def add_button(self,  instance):
        self.cont += 1
        self.layout.add_widget(Button(text = 'Button' + str(self.cont)))

class ExampleApp(App):
    def build(self):
        return MainWindow()

if __name__ == "__main__":
    ExampleApp().run()

正在运行的示例:

enter image description here

PD :代码只是一个简单的示例,经过测试但可能包含错误。

答案 1 :(得分:0)

使用GridLayout但使用BoxLayouts而不是按钮填充它。垂直定位每个BoxLayouts并填充其中的按钮。