2025-09-02
Python
00
请注意,本文编写于 183 天前,最后修改于 182 天前,其中某些信息可能已经过时。

目录

目录
布局
FloatLayout
BoxLayout
BoxLayout间距
AnchorLayout布局(锚点布局)
GridLayout (网格布局)
GridLayout设置布局大小
GridLayout为部件指定大小
设置列宽行高
布局的宽高
PageLayout 布局
PageLayout布局基本属性
RelativeLayout布局
ScatterLayout 分散布局
StackLayout 堆栈布局
例子:计时器
布局
计时器

只是个人学习的时候的一些笔记,如果有什么错误的地方还请各位勿喷,手下留情,期待您的指正。 定期会更新文章到www.sea-whales.cn我的个人网站中,有兴趣的小伙伴可以进来看看

目录

【Kivy】布局 FloatLayout、BoxLayout [学习分享](二)

【Kivy】布局 AnchorLayout、GridLayout [学习分享](三)

【Kivy】布局 PageLayout、RelativeLayout [学习分享](四)

【Kivy】布局 ScatterLayout 、StackLayout [学习分享](五)

布局

FloatLayout

py文件

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.floatlayout import FloatLayout class FloatLayoutWidget(FloatLayout): def __init__(self): super(FloatLayoutWidget, self).__init__() class FloatLayoutApp(App): def build(self): return FloatLayoutWidget() if __name__ == '__main__': FloatLayoutApp().run()

kv文件

python
# 自定义按钮 <Button> font_size: 40 # 字体大小 size_hint: .3, .4 # 按钮大小 <FloatLayoutWidget> # 定义页面 canvas: # 设置背景颜色 Color: rgba: [.2, .4, .5, .6] Rectangle: size: self.size pos: self.pos Button: # 使用自定义按钮 text: "BT1" # 按钮显示文本 background_color: 1, 0, 0, 1 # 按钮背景颜色 pos_hint: {'x': 0, 'top': 1} # 按钮位置 Button: text: "BT2" background_color: .2, .3, .4, .5 pos_hint: {'x': .35, 'y': .3} Button: text: "BT3" background_color: .5, .4, .3, .2 pos_hint: {'x': .7, 'bottom': 0} Button: text: "BT4" background_color: 1, 0, 0, 1 pos_hint: {'x': 0.7, 'top': 1} Button: text: "BT5" background_color: 1, 0, 0, 1 pos_hint: {'x': 0, 'bottom': 1}

BoxLayout

盒子布局,可以将部件水平或者垂直排列的布局。类似于安卓的线性布局。如果没有限制任何大小,部件将会以10px间距平分父窗口大小。

只用Python进行布局的话如下:

python
# !/usr/bin/env python3 # -*- coding: utf8 -*- from kivy.app import App from kivy.graphics import Rectangle, Color from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button class BoxLayoutWidget(BoxLayout): def __init__(self): super(BoxLayoutWidget, self).__init__() # 设置背景颜色 with self.canvas: Color(.4, .5, .02, .3) self.rect = Rectangle(pos=self.pos, size=self.size) self.bind(pos=self.update_rect, size=self.update_rect) # 新建一个指定尺寸的按钮 button1 = Button(text='Hello BoxLayout1', size_hint=(.3, .2), pos=(200, 40), background_color=(1, 1, 1, 1)) button2 = Button(text='Hello BoxLayout2', size_hint=(.2, .2), pos=(200, 40), background_color=(.6, .5, .8, .3)) # 将按钮加到布局内 self.add_widget(button1) self.add_widget(button2) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size class BoxLayoutApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': BoxLayoutApp().run()

或者配合kv文件进行布局:

python代码如下

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) class BoxLayoutTApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': BoxLayoutTApp().run()

kv文件如下:(kv文件创建遵守kv命名规则)

<Button> font_size: 50 <BoxLayoutWidget> canvas: Color: rgba: [.2, .4, .5, .6] Button: text: "BT1" background_color: 1, 0, 0, 1 Button: text: "BT2" background_color: 1, 1, 1, 1 Button: text: "BT3" background_color: 0, 1, 0, 1 Button: text: "BT4" background_color: 1, 0, 1, 1 Button: text: "BT5" background_color: 0, 1, 1, 1

默认BoxLayout排版是纵向排版,若需要改为横向排版则可在KV文件里添加参数orientation: "vertical" 若是使用python实现则可以将实例化BoxLayout时,添加参数BoxLayout(orientation="vertical")

BoxLayout间距

BoxLayout布局中间距有两种形式:

  • 布局和子级之间填充是需要使用padding,默认为[0, 0, 0, 0] ,四个参数分别为 [padding_left, padding_top, padding_right, padding_bottom] 从右下脚开始顺时针一一对应。(左,上,右,下);同时padding还接受两个参数形式[padding_horizontal, padding_vertical] 分别是水平边距和竖直边距;或者一个参数形式[padding]代表周围边距。
  • 子级和子级之间填充需要使用spacing, 默认为 0
<Button> font_size: 10 <BoxLayoutWidget> orientation: "vertical" # 横向排版 padding: [10, 20, 30, 40] # 设置间距 canvas: Color: rgba: [.2, .4, .5, .6] Button: text: "BT1" # 显示文本,.KV默认是不支持中文 background_color: 1, 0, 0, 1 Button: text: "BT2" background_color: 1, 1, 1, 1 BoxLayout: orientation: "vertical" # 设置间距 spacing: 20 Button: text: "BT3" background_color: 0, 1, 0, 1 Button: text: "BT4" background_color: 1, 0, 1, 1 Button: text: "BT5" size_hint_y: .15 # 设置按钮大小 background_color: 0, 1, 1, 1

AnchorLayout布局(锚点布局)

锚点布局可以将子部件放在 左上、中上、右上、左中、正中、右中、左下、中下、右下 ,9个位置处。只需要指定anchor_xanchor_y属性即可。

  • anchor_x 默认值为center,可以且只可以接受leftrightcenter,分别为左、右和中。
    • anchor_y 默认值为center,可以且只可以接受topbottomcenter,分别为上、下和中。

python代码实现如下:

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.anchorlayout import AnchorLayout from kivy.uix.button import Button from kivy.graphics import Rectangle, Color class AnchorLayoutWidget(AnchorLayout): def __init__(self): super(AnchorLayoutWidget, self).__init__() # 设置颜色 with self.canvas: Color(1, 1, 1, 1) self.rect = Rectangle(pos=self.pos, size=self.size) self.bind(pos=self.update_rect, size=self.update_rect) # 嵌套第一个布局 anchor_first = AnchorLayout(anchor_x='left', anchor_y='top') anchor_first.add_widget(Button(text='left-top', size_hint=[.3, .3], background_color=[0, 0, 0, 1])) # 嵌套第二个布局 anchor_second = AnchorLayout(anchor_x='center', anchor_y='top') anchor_second.add_widget(Button(text='center-top', size_hint=[.3, .3], background_color=[0, 0, 1, 1])) # 嵌套第三个布局 anchor_third = AnchorLayout(anchor_x='right', anchor_y='top') anchor_third.add_widget(Button(text='right-top', size_hint=[.3, .3], background_color=[0, 1, 1, 1])) # 嵌套第四个布局 anchor_fourth = AnchorLayout(anchor_x='left', anchor_y='center') anchor_fourth.add_widget(Button(text='left-center', size_hint=[.3, .3], background_color=[1, 1, 0, 1])) # 嵌套第五个布局 anchor_fifth = AnchorLayout(anchor_x='center', anchor_y='center') anchor_fifth.add_widget(Button(text='center-center', size_hint=[.3, .3], background_color=[0, 1, 0, 1])) # 嵌套第六个布局 anchor_sixth = AnchorLayout(anchor_x='right', anchor_y='center') anchor_sixth.add_widget(Button(text='right-center', size_hint=[.3, .3], background_color=[1, 0, 1, 1])) # 嵌套第七个布局 anchor_seventh = AnchorLayout(anchor_x='left', anchor_y='bottom') anchor_seventh.add_widget(Button(text='left-bottom', size_hint=[.3, .3], background_color=[0, 1, .5, 1])) # 嵌套第八个布局 anchor_eighth = AnchorLayout(anchor_x='center', anchor_y='bottom') anchor_eighth.add_widget(Button(text='center-bottom', size_hint=[.3, .3], background_color=[1, .5, 1, .5])) # 嵌套第九个布局 anchor_ninth = AnchorLayout(anchor_x='right', anchor_y='bottom') anchor_ninth.add_widget(Button(text='right-bottom', size_hint=[.3, .3], background_color=[.5, 1, 1, .5])) self.add_widget(anchor_first) self.add_widget(anchor_second) self.add_widget(anchor_third) self.add_widget(anchor_fourth) self.add_widget(anchor_fifth) self.add_widget(anchor_sixth) self.add_widget(anchor_seventh) self.add_widget(anchor_eighth) self.add_widget(anchor_ninth) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size class AnchorLayoutApp(App): def build(self): return AnchorLayoutWidget() if __name__ == '__main__': AnchorLayoutApp().run()

或者配合kv文件进行布局: python代码如下:

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) class BoxLayoutTApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': BoxLayoutTApp().run()

kv文件如下:

<Button> font_size: 10 size_hint: .3, .3 <AnchorLayoutWidget> padding: 20 AnchorLayout: anchor_x: 'left' anchor_y: 'top' Button: background_color: 0, 0, 0, 1 text: 'left-top' AnchorLayout: anchor_x: 'center' anchor_y: 'top' Button: text: 'center-top' background_color: 0, 0, 1, 1 AnchorLayout: anchor_x: 'right' anchor_y: 'top' Button: text: 'right-top' background_color: 0, 1, 1, 1 AnchorLayout: anchor_x: 'center' anchor_y: 'center' Button: text: 'center-center' background_color: 1, 1, 0, 1 AnchorLayout: anchor_x: 'left' anchor_y: 'center' Button: text: 'left-center' background_color: 0, 1, 0, 1 AnchorLayout: anchor_x: 'right' anchor_y: 'center' Button: text: 'right-center' background_color: 1, 0, 1, 1 AnchorLayout: anchor_x: 'left' anchor_y: 'bottom' Button: text: 'left-bottom' background_color: 0, 1, .5, 1 AnchorLayout: anchor_x: 'center' anchor_y: 'bottom' Button: text: 'center-bottom' background_color: 1, .5, 1, .5 AnchorLayout: anchor_x: 'right' anchor_y: 'bottom' Button: text: 'right-bottom' background_color: .5, 1, 1, .5

GridLayout (网格布局)

可以将子部件排列成多行多列的矩阵,根据布局配置按照子部件的索引为每一个子部件分配位置。新建网格布局的时候,需要设置具体的行(cols)和列(rows)数,作为约束。否则设置是无效的。 设置具体的行列后,当子部件变化时,布局就会根据改值进行扩展,但是总数不会超过设置的上限值。

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.gridlayout import GridLayout from kivy.uix.button import Button from kivy.graphics import Rectangle, Color class GridLayoutWidget(GridLayout): def __init__(self): super(GridLayoutWidget, self).__init__() with self.canvas: Color(1, 1, 1, 1) self.rect = Rectangle(pos=self.pos, size=self.size) self.bind(pos=self.update_rect, size=self.update_rect) self.cols = 3 self.rows = 3 for i in range(8): btn = Button(text=f'BTN_{i}', background_color=(0.2, .2, .4)) self.add_widget(btn) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size class GridLayoutApp(App): def build(self): return GridLayoutWidget() if __name__ == '__main__': GridLayoutApp().run()

配合kv文件代码如下:

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.gridlayout import GridLayout class GridLayoutWidget(GridLayout): def __init__(self): super(GridLayoutWidget, self).__init__() class GridLayoutApp(App): def build(self): return GridLayoutWidget() if __name__ == '__main__': GridLayoutApp().run()

kv代码

<Button> font_size: 10 size_hint: .3, .4 <GridLayoutWidget> rows:3 cols:3 padding: 15 spacing: 20 Button: background_color: 0, 1, 0, 1 text: 'btn_1' Button: background_color: .1, 0, 1, 1 text: 'btn_2' Button: background_color: 0, .5, .4, 1 text: 'btn_3' Button: background_color: 0, 1, 0, .5 text: 'btn_4'

GridLayout设置布局大小

GridLayout布局种,可以使用部件本身属性为其指定大小,若要对部件设置固定宽度,在设置之前则需要将size_hint_x设置为None

GridLayout为部件指定大小

需要使用col_force_default属性,其默认值False,表示不使用列默认宽度。需要将col_force_default设置为True。并且在没有给子部件设置widthsize_hint_x的属性的情况下,使用默认的列宽。列宽的默认值为0。所以还需要指定一个具体的值,使用col_default_width可以设置成功。同上,对与设置行高也可以相同的方法将row_force_default设置True,并且row_default_height设置值。

设置列宽行高

布局的宽高

可以使用cols_minimum设置属性的列宽,cols_minimum属性接受的值是一个字典,字典的键为列号,值为像素值。例如:cols_minimum:{0: 130, 1:140} 将第一列设置为130像素,第二列设置为140像素。 执行一下代码后,可以发现,从执行顺序的优先级来说,可以按照如下顺序: col_default_width < cols_minimum < width。 同理,也可以通过rows_minimum设置属性的行高rows_minimum: {0: 50}。 可参考如下kv代码:

<Button> font_size: 50 size_hint: .3, .4 <GridLayoutWidget> rows:3 # 设置行数 cols:3 # 设置列数 padding: 15 # 设置间距 spacing: 20 # 设置间距 col_force_default: True # 强制使用默认列宽 col_default_width: 200 # 设置默认,列宽 row_force_default: True # 强制使用默认行高 row_default_height: '34px' # 设置默认行高 cols_minimum:{0: 130, 1:140} # 设置列宽 rows_minimum: {0: 50} # 设置行高 canvas: Color: rgba: .3,.3,.5,.5 Rectangle: size: self.size pos: self.pos Button: background_color: 0, 1, 0, 1 text: 'btn_1' size_hint_x: None width: '300px' Button: background_color: .1, 0, 1, 1 text: 'btn_2' Button: background_color: 0, .5, .4, 1 text: 'btn_3' Button: background_color: 0, 1, 0, .5 text: 'btn_4'

PageLayout 布局

PageLayou布局和前面几种布局方式是有差异的,他更倾向与动态布局,使用这个布局可以创建一个简单的多页面布局。可以在这些布局之间随意跳转,此布局每个子部件都作为一个单独的页面,所以此布局并不支持size_hintpos_hint: 例如如下: 会生成一个可以自由左右拉的按钮。

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.uix.pagelayout import PageLayout from kivy.app import App from kivy.uix.button import Button class PageLayoutWidget(PageLayout): def __init__(self, **kwargs): super(PageLayoutWidget, self).__init__() btn = Button(text='btn1', background_color=[0.3,.9,.2,1]) btn2 = Button(text='btn2', background_color=[.1,.5,.4,1]) self.add_widget(btn) self.add_widget(btn2) class PageLayoutPyApp(App): def build(self): return PageLayoutWidget() if __name__ == '__main__': PageLayoutPyApp().run()

KV实现布局

# pagelayout.kv <PageLayoutWidget> border: '100dp' # 设置边界,如果不设置默认为50dp Button: text:'Page0' background_color: 0.3, .2, .5, 1 Button: text:'Page1' background_color: 0.4, .4, .6, 1 Button: text:'Page2' background_color: 0.6, .6, .8, 1 Button: text:'Page3' background_color: 0.8, .8, 1, 1

Python配合

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.pagelayout import PageLayout class PageLayoutWidget(PageLayout): def __init__(self): super(PageLayoutWidget, self).__init__() class PageLayoutApp(App): def build(self): return PageLayoutWidget() if __name__ == '__main__': PageLayoutApp().run()

PageLayout布局基本属性

  • border : 指定两边边界大小,如果我们没有指定的话默认是50dp.前面的kv中也对这进行写入,测试时可以将对应行去掉后进行测试。
  • page: 设置默认显示哪一页、
  • swipe_threshold: 设置翻页灵敏度 例如: swipe_threshold: .8
  • anim_kwargs: 属性设置’t‘翻页动画和’d‘持续时间,例如: anim_kwargs: {'d':10, 't': 'linear'}。 这边t中有哪些参数暂时不做过多说明,后期会细说。

可以尝试下,当以上属性都设置了,页面之间切换的动画被延长到10秒了,并且翻页的灵敏度也要滑动到80%时以上才会被判定为翻页的动作。

RelativeLayout布局

相对布局,此布局的操作方式与前面的FloatLayout基本是相同的,只是在定位的时候我们使用的x,center_x,right,y,center_y,top这些属性是想对于他的父布局的,而不是相对于窗口。 其实任何布局,当布局的位置属性更改时,小部件都会移动。 接下来我们看看如何初始化一个RelativeLayou布局。 老样子,使用python代码和kv代码文件两种方式实现。

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.uix.relativelayout import RelativeLayout from kivy.uix.button import Button from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.graphics import Color, Rectangle class MyButton(Button): # 自定义按钮属性,将公共属性提出来 def __init__(self, **kwargs): super(MyButton, self).__init__(**kwargs) self.font_size = 20 self.size_hint = [.2, .2] class RelativelayoutWidget(RelativeLayout): pass class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) with self.canvas: Color(1, 1, 1, 1) self.rect = Rectangle(pos=self.pos, size=self.size) # 绑定事件 self.bind(pos=self.update_rect, size=self.update_rect) box_relative = RelativelayoutWidget() btn1 = MyButton(text='btn1', pos_hint={'right': 1, 'top': 1}, background_color=(.1, .2, .3, 1)) btn2 = MyButton(text='btn2', pos_hint={'x': 0, 'top': 1}, background_color=(.1, .2, .3, 1)) RelativeBtn3 = MyButton(text='RelativeBtn3', pos_hint={'center_x': .5, 'center_y': .5}, background_color=(.1, .2, .3, 1)) RelativeBtn4 = MyButton(text='RelativeBtn4', pos_hint={'x': 0, 'y': 0}, background_color=(.1, .2, .3, 1)) RelativeBtn5 = MyButton(text='RelativeBtn5', pos_hint={'right': 1, 'y': 0}, background_color=(.1, .2, .3, 1)) for i in [btn1, btn2, RelativeBtn3, RelativeBtn4, RelativeBtn5]: box_relative.add_widget(i) self.add_widget(BoxLayout()) self.add_widget(box_relative) def update_rect(self, *args): # 设置背景尺寸, 可忽略 self.rect.pos = self.pos self.rect.size = self.size class RelativeLayoutApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': RelativeLayoutApp().run()

以上代码运行后,会出现半边是空白,另外半边是有在四个角落和中间五个按钮,那是因为我们把按钮在第42行的时候,全部加在了Relativelayout布局内了,然后右边放空一个BoxLayout布局进行占位,不加任何控件,因为Relativelayout布局里面的控件是按照Relativelayout布局的位置和大小进行定位的,并非按照我们最开始初始化的大的那个BoxLayout布局进行定位的,所以里面的控件都是相对于Relativelayout布局的位置进行放置。 接下一样,我们用kv文件配合python 的方式去实现上面的样子。

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.uix.boxlayout import BoxLayout from kivy.app import App class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) class RelativeLayoutApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': RelativeLayoutApp().run()

kv代码

<Button> font_size:20 size_hint: .2,.3 <BoxLayoutWidget> canvas: Color: rgba: 1,1,1,1 Rectangle: size: self.size pos: self.pos BoxLayout: RelativeLayout: Button: text:"btn1" background_color: .1,.2,.3,1 pos_hint:{'right':1, 'top':1} Button: text:"btn2" background_color: .1,.2,.3,1 pos_hint:{'x': 0, 'top': 1} Button: text:"RelativeBtn3" background_color: .1,.2,.3,1 pos_hint:{'center_x': .5, 'center_y': .5} Button: text:"RelativeBtn4" background_color: .1,.2,.3,1 pos_hint:{'x': 0, 'y': 0} Button: text:"RelativeBtn5" background_color: .1,.2,.3,1 pos_hint:{'right': 1, 'y': 0}

ScatterLayout 分散布局

ScatterLayout布局与RelativeLayout布局相似,当变更位置的时候,布局内的小部件也会随着父布局一起相对更改,因为这个布局主要由Scatter小部件实现,所以是可以实现自由的平移,旋转,缩放等布局的。 我们来看下, 使用Python是如何实现的。

# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.uix.boxlayout import BoxLayout from kivy.app import App from kivy.uix.scatterlayout import ScatterLayout from kivy.uix.image import AsyncImage from kivy.graphics import Rectangle, Color class ScatterLayoutWidget(ScatterLayout): pass class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) with self.canvas: Color(1, 1, 1, 1) self.rect = Rectangle(pos=self.pos, size=self.size) self.bind(pos=self.update_rect, size=self.update_rect) scatter_layout = ScatterLayoutWidget() image = AsyncImage(source='https://blogcdn.sea-whales.cn/blog/typecho/11.jpg') scatter_layout.add_widget(image) self.add_widget(scatter_layout) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size class ScatterLayoutApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': ScatterLayoutApp().run()

运行以上python代码,将会出现一个图片,且在窗体中间加载,我们可以使用鼠标单击图片,模拟手指点击进行图片的拖动和缩放、旋转操作。

kv配合python实现如下:

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout class BoxLayoutWidget(BoxLayout): def __init__(self, **kwargs): super(BoxLayoutWidget, self).__init__(**kwargs) class ScatterLayoutApp(App): def build(self): return BoxLayoutWidget() if __name__ == '__main__': ScatterLayoutApp().run()

kv文件

<BoxLayoutWidget> canvas: Color: rgba: 1,1,1,1 ScatterLayout: AsyncImage: source: 'https://blogcdn.sea-whales.cn/blog/typecho/11.jpg' ScatterLayout: Image: source: 'scatter_image.jpg'

StackLayout 堆栈布局

堆栈布局中只要不超过布局的范围,就可以进行垂直或者水平的排列子项,并且各个小部件的大小可以不需要相同,StackLayout布局可以通过orientation属性进行指定布局方向,默认值为lr-tb。 我们看看堆栈排列有哪些排序排列。

  • 按行排列:lr-tb,lr-bt,rl-tb,rl-bt
  • 按列排序:tb-lr,bt-lr,tb-rl,bt-rl

我们看看上面的l、r、t、b 分别代表什么。

  • l 代表的是'left'的缩写,代表左
  • r 代表的是'right'的缩写,代表右
  • t 代表的是'top'的缩写,代表上
  • b 代表的是'bottom'的缩写,代表下

那么我们就可以将'lr'理解为从左到右,'tb'理解为从上到下,以此类推。 'lr-tb'可以看成先按行从左到右,当前窗口行满后再按列从上到下,那么'tb-lr'则可以看成先按列从上到下,当前窗口列满后,按从左到右排列。其他方式,以此类推。

接下来我们来写一个'lr-tb'排列,不同大小的布局,且按照'lr-tb'方式布局长度递增。

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.uix.button import Button from kivy.uix.stacklayout import StackLayout from kivy.app import App from kivy.graphics import Rectangle, Color class StackLayoutWidget(StackLayout): def __init__(self, **kwargs): self.orientation = 'lr-tb' super(StackLayoutWidget, self).__init__(**kwargs) with self.canvas: Color(1, 1, 1, 1) # 设置底色为白色 self.rect = Rectangle(size=self.size, pos=self.pos) self.bind(size=self.update_rect, pos=self.update_rect) for i in range(30): # 将按钮的高度控制在20%,长度初始为50,随着按钮越多按钮越大递增。 btn = Button(text=f'Btn_f{i}', width=50 + i * 8, size_hint=(None, 0.20)) self.add_widget(btn) def update_rect(self, *args): self.rect.pos = self.pos self.rect.size = self.size class StackLayoutApp(App): def build(self): return StackLayoutWidget() if __name__ == '__main__': StackLayoutApp().run()

前面已经写了很多从Python 文件改为Python和kv文件配合的情况了,这个我就不单独写了。 我们来看看StackLayout有哪些属性。

  • orientation: 前面我们说过,这个属性是用于决定布局内子部件的排列方式,也说明了具体有哪些属性。
  • padding:这个属性有看前面的也不陌生,是用于控制布局和部件之间的间距的参数。接受的是一个list,可以是四个和两个和一个。四个时分别是[padding_left, padding_top, padding_right, padding_bottom] 左、上、右、下 。两个时分别是[padding_horizontal,padding_vertical] 水平、垂直 两个方向。一个时代表控件四个方向的间距。他们的默认值都为0
  • spacing: 这属性和前面的属性也是一样的用于控制部件和部件之间间距。他可以接受两个和一个参数,也是list。不同数量参数和padding表示的一致。

以上三个参数StackLayout常用的属性,还有几个就是布局会根据子部件自动设置一些属性。我们来看下分别是哪些(顾名思义即可):

  • minimum_height:最低高度。
  • minimum_width: 最小宽度
  • minimum_size:最小尺寸(可同时设置最低高度和最小宽度)

以上就是StackLayout参见的属性,就不做例子进行解释了。如果是按照前面一步步看过来的,也能很快理解意思。

例子:计时器

布局

# !/usr/bin/env python3 # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout class ClockBoxLayout(BoxLayout): def __init__(self, **kwargs): super(ClockBoxLayout, self).__init__(**kwargs) class ClockApp(App): def build(self): return ClockBoxLayout() if __name__ == '__main__': # 设置页面背景 from kivy.core.window import Window Window.clearcolor = [.8, .8, .8, 1] ClockApp().run()

kv文件

<ClockBoxLayout>: orientation: 'vertical' Label: id: time_label_id text: '[b]00[/b]:00:00' font_size: 60 markup: True

计时器

具有暂停和重置功能

python
# !/usr/bin/env python3 # -*- coding: utf-8 -*- from time import strftime from kivy.app import App from kivy.uix.anchorlayout import AnchorLayout from kivy.clock import Clock class ClockBoxLayout(AnchorLayout): def __init__(self, **kwargs): super(ClockBoxLayout, self).__init__(**kwargs) self.timing_flag = False self.timing_seconds = 0 self.on_start() def on_start(self): # 设置clock 每0秒执行一次,代表实时进行不间断刷新。 Clock.schedule_interval(self.update_time, 0) def update_time(self, nap): if self.timing_flag: self.timing_seconds += nap # 通过ID获取time_label_id的控件,并且设置text的属性值 self.ids.time_label_id.text = strftime('[b]%H[/b]:%M:%S') m, s = divmod(self.timing_seconds, 60) self.ids.stopwatch.text = ('%02d:%02d.[size=40]%02d[/size]' % (int(m), int(s), int(s * 100 % 100))) def start_on_stop(self): self.ids.start_stop_button_id.text = 'Start' if self.timing_flag else 'Stop' self.timing_flag = not self.timing_flag def reset_clock(self): if self.timing_flag: self.ids.start_stop_button_id.text = 'Start' self.timing_flag=False self.timing_seconds = 0 class ClockApp(App): def build(self): return ClockBoxLayout() if __name__ == '__main__': # 设置页面背景 from kivy.core.window import Window Window.clearcolor = [.8, .8, .8, 1] ClockApp().run()

kv文件

<MyButton@Button> font_size: 25 bold: True border: (2,2,2,2) <ClockBoxLayout>: # 异步加载背景图像 AsyncImage: source: 'https://blogcdn.sea-whales.cn/blog/typecho/11.jpg' BoxLayout: # 设置布局 orientation: 'vertical' Label: id: time_label_id # 添加ID属性,通过ID属性进行对控件的获取 text: '[b]00[/b]:00:00' font_size: 60 markup: True # BoxLayout: orientation: 'horizontal' padding: 20 spacing: 20 size_hint:(1, None) height: 90 MyButton: id: start_stop_button_id text:'start' on_press: root.start_on_stop() MyButton: text: 'Reset' on_press: root.reset_clock() # 触发事件 Label: id: stopwatch text: '00:00.[size=40]00[/size]' font_size: 60 markup: True

本文作者:sea-whales

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!