只是个人学习的时候的一些笔记,如果有什么错误的地方还请各位勿喷,手下留情,期待您的指正。 定期会更新文章到www.sea-whales.cn我的个人网站中,有兴趣的小伙伴可以进来看看
【Kivy】布局 FloatLayout、BoxLayout [学习分享](二)
【Kivy】布局 AnchorLayout、GridLayout [学习分享](三)
【Kivy】布局 PageLayout、RelativeLayout [学习分享](四)
【Kivy】布局 ScatterLayout 、StackLayout [学习分享](五)
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}
盒子布局,可以将部件水平或者垂直排列的布局。类似于安卓的线性布局。如果没有限制任何大小,部件将会以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布局中间距有两种形式:
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
锚点布局可以将子部件放在 左上、中上、右上、左中、正中、右中、左下、中下、右下 ,9个位置处。只需要指定anchor_x和anchor_y属性即可。
anchor_x 默认值为center,可以且只可以接受left、right、center,分别为左、右和中。anchor_y 默认值为center,可以且只可以接受top、bottom、center,分别为上、下和中。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
可以将子部件排列成多行多列的矩阵,根据布局配置按照子部件的索引为每一个子部件分配位置。新建网格布局的时候,需要设置具体的行(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布局种,可以使用部件本身属性为其指定大小,若要对部件设置固定宽度,在设置之前则需要将size_hint_x设置为None。
需要使用col_force_default属性,其默认值False,表示不使用列默认宽度。需要将col_force_default设置为True。并且在没有给子部件设置width和size_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'
PageLayou布局和前面几种布局方式是有差异的,他更倾向与动态布局,使用这个布局可以创建一个简单的多页面布局。可以在这些布局之间随意跳转,此布局每个子部件都作为一个单独的页面,所以此布局并不支持size_hint和pos_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()
border : 指定两边边界大小,如果我们没有指定的话默认是50dp.前面的kv中也对这进行写入,测试时可以将对应行去掉后进行测试。page: 设置默认显示哪一页、swipe_threshold: 设置翻页灵敏度 例如: swipe_threshold: .8anim_kwargs: 属性设置’t‘翻页动画和’d‘持续时间,例如: anim_kwargs: {'d':10, 't': 'linear'}。 这边t中有哪些参数暂时不做过多说明,后期会细说。可以尝试下,当以上属性都设置了,页面之间切换的动画被延长到10秒了,并且翻页的灵敏度也要滑动到80%时以上才会被判定为翻页的动作。
相对布局,此布局的操作方式与前面的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布局与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布局可以通过orientation属性进行指定布局方向,默认值为lr-tb。
我们看看堆栈排列有哪些排序排列。
lr-tb,lr-bt,rl-tb,rl-bttb-lr,bt-lr,tb-rl,bt-rl我们看看上面的l、r、t、b 分别代表什么。
那么我们就可以将'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] 水平、垂直 两个方向。一个时代表控件四个方向的间距。他们的默认值都为0spacing: 这属性和前面的属性也是一样的用于控制部件和部件之间间距。他可以接受两个和一个参数,也是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 许可协议。转载请注明出处!