canvas
canvas.before
canvas.after
的区别InstructionGroup
使用TextInput
设置为单行数值输入框FloatLayout
布局使用自定义按钮
使用canvas
绘图来自定义一个圆形按钮,作为控制按钮
在背景中绘制一个圆形,并设置backgroud_color
为透明,代码如下:
:
# 背景
canvas.before:
Color:
rgb:(1, 0, 0)
Ellipse:
size: (min(self.width, self.height), min(self.width, self.height))
pos: (self.center_x - min(self.width, self.height) / 2, self.center_y - min(self.width, self.height) / 2)
background_color: (0, 0, 0, 0) # 设置背景透明
绑定按钮的state
, 用来处理on_press
事件时的颜色改变,代码如下:
class EllipticButton(Button):
"""椭圆按钮类"""
def __init__(self, **kwargs):
super(EllipticButton, self).__init__(**kwargs)
self.bind(state=self.change_foreground_color)
def change_foreground_color(self, s, state):
"""修改前景色"""
front_color = Color(0, 1, 0, .8) # 修改此处可更改前景色
front = InstructionGroup()
front.add(front_color)
front.add(Rectangle(pos=self.pos, size=self.size))
if state == 'normal':
self.canvas.after.clear()
else:
self.canvas.after.add(front)
当按钮按下时,前景色为绿色 80%透明度
数字输入框
自定义一个数字输入框,仅允许输入规定范围的数字数值。
初始化函数如下:
def __init__(self, **kwargs):
super(NumericTextInput, self).__init__(**kwargs)
self.halign = 'center' # 文本居中
self.multiline = False # 单行
self.size_hint_y = None # 高度为绝对值
# self.height = self.line_height
self.input_filter = 'int' # 仅可输入数值
self.bind(text=self.on_text)
self.bind(value=self.on_value)
其中value
为NumericProperty
,用来指示输入框文本代表的数值,另外,定义一个属性值_max
,用来规定输入框允许输入的最大值,代码如下:
_max = NumericProperty(0) # 可现实最大数值
value = NumericProperty(0) # 数值
当文本改变时,处理程序如下:
def on_text(self, sender, txt):
"""文本值改变事件"""
if txt == '':
self.text = '00'
else:
self.value = int(txt)
if self.value >= self._max: # 当值大于超过最大值时,设置值为0
self.text = "{:0>2d}".format(0)
self.select_all()
else: # 格式化显示样式
self.text = "{:0>2d}".format(self.value)
当数值改变时,处理程序如下:
def on_value(self, sender, v):
"""修改文本"""
self.text = "{:0>2d}".format(self.value)
倒计时程序
倒计时工作流程
def thread_counting(self):
"""倒计时线程"""
start = time.time()
while self.is_run:
if self.is_paused:
self.stop_time = time.time() - start - self.timer
else:
self.timer = time.time() - start - self.stop_time
if self.timer >= self.counter: # 停止计数
self.is_run = False
time.sleep(.01)
timer
为NumericProperty
,当值改变时,自动刷新倒计时设置器的值,即:
def update_timer(self, s, t):
"""更新倒数器"""
remain = int(self.counter - t) # 剩余倒计时值
self.t_hour.value = remain // 3600
self.t_min.value = (remain // 60) % 60
self.t_sec.value = remain % 60
self.ids.label_timer.text = "{:0>2d}".format(99 - int(t * 100) % 100)
FloatLayout布局
倒计时设置器布局在一个FloatLayout
中,部分示例如下:
FloatLayout:
size_hint: (1, .8)
BoxLayout:
size_hint: (.5, None)
height: lb.texture_size[1] # 设置高度为标签文本高度
pos_hint: {'x': .25, 'y': .5}
# 倒计时小时值手动输入框
NumericTextInput:
id: carousel_hour
_max: 100
font_size: 100
height: lb.texture_size[1]
Label:
id: lb
text: ':'
font_size: 100
size: self.texture_size
其中size_hint: (.5, None)
的设置,可将FloatLayout
中的BoxLayout
的宽度设置为50%,高度设置为绝对值,height: lb.texture_size[1]
设置BoxLayout
的高度值。pos_hint: {'x': .25, 'y': .5}
设置其位置相对值。
# 控制按钮-设置倒计时小时值
Button:
text: '+'
size_hint: (None, None)
size: carousel_hour.size
pos: carousel_hour.pos[0], carousel_hour.pos[1] + carousel_hour.height
on_press: carousel_hour.value = (carousel_hour.value + 1) % carousel_hour._max
Button:
text: '-'
size_hint: (None, None)
size: carousel_hour.size
pos: carousel_hour.pos[0], carousel_hour.pos[1] - carousel_hour.height
on_press: carousel_hour.value = (carousel_hour.value - 1) % carousel_hour._max
在FloatLayout
中添加按钮,按钮位置相对于其设置的倒计时输入框而改变。
运行示例如下:
手机运行示例:
源码地址:https://github.com/babylco0/python3_examples/tree/master/count