写在最前:
开发App的主流语言中应该是Java,但是苦于没有学过Java但目前又没那么多时间重新学,因此就想着用已经入门的Python开发两个App练手,学习的过程中看过很多资料,也踩过很多坑,于是就想着将自己的经验写出来分享给大家,希望大家可以少踩些坑,更顺利地学习。本次《Python开发App实战》总共分为4个部分,第一部分是Kivy的入门教程,第二部分是基于Kivy实现一个具有计时器和秒表功能的表,第三部分是基于Kivy实现一个科学计算器,第四部分是Kivy向移动设备的打包移植。前三个部分博主是已经完成的,虽然第四部分相对简单,但是比较方便的一种方法是使用Kivy提供的Buildozer打包,由于博主研究室的网络最近处于瘫痪状态,因此唯一一台ubuntu设备无法使用,博主在自己的macbook上打包了好多次也因为一些不知原因的问题没有成功,在ubuntu的虚拟机上打包又提示内存空间不足,因此想等到研究室网络恢复,打包移植成功后再更新第四部分。
本次开发的环境如下:
Python: 3.6.6
Kivy: 1.11.1
OS: MacOS(Ubuntu自然ok)
IDE:Pycharm EDU
了解Kivy
好了,开始正题。
Kivy于2011年初首次发布。该跨平台的Python框架可以部署到Windows,Mac,Linux和树莓派上。它除了常规的键盘和鼠标输入外,还支持多点触控事件。Kivy甚至还支持其图形的GPU加速,因为它们是用OpenGL ES2构建的。Kivy使用的是MIT许可证,因此你可以将该库用于免费和商业软件。
Kivy不会尝试使用本机控件或小部件。它的所有小部件都是定制的,因此用Kivy开发的App在所有平台上的GUI都是一样的,不过缺点可能就是你开发的App的GUI将与用户的本机应用程序不同。
安装Kivy
Kivy具有许多依赖关系,建议将其安装到Python虚拟环境中。没有用过虚拟环境的千万不要劝退,这里简单的介绍一下虚拟环境:
虚拟环境可以理解于开辟出来的专用的一块环境,它独立于你系统的环境,因为在实际项目中可以根据需求或者库不同需要不同版本的依赖关系,比如有的项目要用Python2,有的要用Python3,有的用Tensorflow1.10,有的用Tensorflow2.0。使用虚拟环境就可以将每个项目完美地独立起来,避免的每次需要把系统整体环境的版本改来改去。用过Pycharm的同学可以理解为软件设置里的project interpreter,你可能每次创建一个工程都会重新安装依赖,这其实就是所谓的虚拟环境。
如果你只是用来做项目而不打算深入了解它,你可以使用Python的内置venv库或virtualenv包。本次教程就使用venv库实现。
先导航到你创建项目的目录下,在terminal输入以下指令创建虚拟环境:
python3 -m venv my_kivy_project
这样就创建成功了一个my_kivy_project的文件夹并且在目录下创建了虚拟环境。
接下来用以下指令来激活环境:
source bin/activate
激活之后你terminal应该变成了这样:
(my_kivy_project) 你的计算机名:my_kivy_project 你的用户名$
不用的时候输入deactivate退出即可。
接下来在激活后的虚拟环境中安装Kivy,如果你已经安装过pip即可以输入以下指令,否则你需要先安装pip:
python -m pip install kivy
如果顺利安装完成后你就可以输入pip list
,然后看到其中有kivy了。
用Kivy的Label实现Hello World
大家学语言之前都是用Hello World开始的吧,那我们今天入门Kivy也从Hello World开始。
创建一个main.py或者其他的什么命名,在里面输入以下程序你就可以看到Hello World了,你可以使用Pycharm这个IDE来编程,在然后在虚拟环境中python main.py来运行。
from kivy.app import App
from kivy.uix.label import Label
class mainApp(App):
def build(self):
label = Label(text='Hello World', size_hint=(.5, .5),
pos_hint={'center_x': .5, 'center_y': .5})
return label
if __name__ == '__main__':
app = mainApp()
app.run()
运行完.py文件后,如果没有出现错误你应该可以看到这个界面:
每个Kivy应用程序都需要继承App
类和重写build()
函数。在这里,你可以编写自己的UI代码或调用定义UI代码的其他函数。这次创建一个Label窗口小部件,并通过定义text
,size_hint
和pos_hint
的数值告诉Kivy创建小部件时要使用的比例和部件的位置。其中size_hint
两个数字的含义是:
第一个数字是x大小提示,指的是控件的宽度。
第二个数字是y大小提示,表示控件的高度。
这两个数字范围为0到1。两个提示的缺省值都是1。
pos_hint
两个值的意思可以参考size_hint
,上面的代码中的两个.5是将label这个部件(widget)在x和y轴上居中。
布置UI
Kivy提供了很多的部件,在接下来的项目中比较常用到的有BoxLayout
,TextInput
, Button
,还有本次用到的Label
等,大家可以根据自己的需求设计UI,然后添加部件,在官网上都可以看到相应的部件函数,如Layout里除了BoxLayout
还有AnchorLayout
,FloatLayout
等,大家可以去用用试试看。
接下来我们就用之后的开发中用的最频繁的BoxLayout和Button来给大家做一个简单的UI演示。
尝试以下的代码
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class boxLayoutExample(App):
def build(self):
layout = BoxLayout(orientation='vertical', spacing=15, padding=10) #创建Layout
buttons = [str(i) for i in range(7)] #设置按键的标签
for i in range(7):
button = Button(text=buttons[i], size_hint=(.5, .5),
pos_hint={"center_x": .5, "center_y": .5})
layout.add_widget(button) #将按键加入到Layout中
return layout
if __name__ == "__main__":
app = boxLayoutExample()
app.run()
如果运行之后没有错的话你将看到如下的界面
参考Hello World部分的代码解释以及本次代码中的注释我们大概可以理解,首先继承App
类然后重写build()
函数,在函数中创建一个BoxLayout
,然后以字符的形式为按钮创建标签,接着用一个循环将按钮添加到Layout中即可。可以在出现的界面上点一下0-6的数字,可以发现确实是按键,可以按下可以弹起。
需要注意的是创建BoxLayout
的时候,里面用到的orientation,spacing,padding的局部变量,它们的含义如下:
- padding:可以通过以下三种方式之一指定Layout及其子元素之间的填充像素:
1.四参数列表: [padding_left,padding_top,padding_right,padding_bottom]
2.两个参数的列表: [padding_horizontal,padding_vertical]
3.单个参数: padding=10 - spacing:可以使用此参数在子窗口小部件之间添加空间。
- orientation:可以更改默认orientation的BoxLayout从水平到垂直。
其他BoxLayout的参数也可以在官网上看到其含义和使用方法,官方手册是很好的工具,大家可以好好利用,顺便锻炼一下英语。
添加事件
和大多数GUI工具包一样,Kivy主要基于事件,它可以响应用户的按键,鼠标事件和触摸事件,此外Kivy还具有时钟的事件。
Kivy也有Properties与之搭配的概念EventDispatcher。属性可帮助您进行验证检查。它们还使您可以在小部件更改大小或位置时触发事件。
承接上面的按键的例子,我们可以通过定义on_press_button()
函数来定义按键后的回调函数,然后用bind()
函数来将该相应的事件绑定到定义的回调函数上。我们就来定义一个回调函数,用来打印出是哪个按键被按下,绑定的事件的相应的按键被按下,添加绑定事件和回调函数的代码段如下所示:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
class boxLayoutExample(App):
def build(self):
layout = BoxLayout(orientation='vertical', spacing=15, padding=10) #创建Layout
buttons = [str(i) for i in range(7)] #设置按键的标签
for i in range(7):
button = Button(text=buttons[i], size_hint=(.5, .5),
pos_hint={"center_x": .5, "center_y": .5})
button.bind(on_press=self.on_press_button)
layout.add_widget(button) #将按键加入到Layout中
return layout
def on_press_button(self, instance):
print('你按下了{}键'.format(instance.text))
if __name__ == "__main__":
app = boxLayoutExample()
app.run()
运行完后出现的界面跟上面UI的例子相同,因为我们没有修改UI的布置,不同的是因为按下按键后触发了on_press
事件,该事件绑定了我们定义的回调函数,因此回调函数中的代码段就被执行,就可以在terminal看到你按下了*键的提示。
KV语言
布局UI不仅可以像上文介绍的那样实现,Kivy还提供了一种称为KV的设计语言,你可以用KV语言实现UI布局。不要看到是一门新的语言就劝退,博主一开始就被劝退了,但实际上学起来还是很快的,因为它虽然是一个语言,但毕竟用来设计UI界面的,所以入门也比较简单。
使用KV语言来实现UI布局可以创建一个名为***.kv的文档实现,也可以在原来的.py文件中添加kivy.bulid.Builder.load_string()
函数,在该函数中添加代码段。完整的程序如下:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string('''
<myLayout>
BoxLayout:
orientation:'vertical'
spacing:15
padding:38
Button:
id:0
text:'0'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:1
text:'1'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:2
text:'2'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:3
text:'3'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:4
text:'4'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:5
text:'5'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
Button:
id:6
text:'6'
size_hint:(.5, .5)
pos_hint:{"center_x": .5, "center_y": .5}
on_press:root.on_press_button(self.text)
''')
class myLayout(BoxLayout):
def __init__(self, **kwargs):
super(myLayout, self).__init__(**kwargs)
def on_press_button(self, instance):
print('你按下了{}键'.format(instance))
class boxLayoutExample(App):
def build(self):
return myLayout()
用以上的代码段与之前不用KV语言的代码段的UI和功能完全相同,大家可以运行一下试试。需要注意创建的myLayout
类中继承了BoxLayout
,并且在主App类的build()
函数中要返回myLayout
类,这样kivy才知道布置的UI是哪个。
细心的同学可以发现,在KV语言中定义的按钮中添加了id
的属性,有了这个属性后就可以通过self.ids['id']
来对相应的部件进行操作,虽然本次的例子中没有用到,但后面的例子会用到,在此先做个铺垫。用了KV语言的好处就是UI布置起来更直观,更符合易读,缺点就是很多功能相同的代码段重复出现,虽然可以复制粘贴,但毕竟还是体力活。在实际应用中大家可以根据自己的需求选择用或者不用KV语言。
有了以上这些基础加上学会使用官方手册,就应该已经入门Kivy了,可以根据自己的需求来实现APP的UI了。入门篇到此结束,下一篇开始我们就开始APP的开发实战!
写在最后
如果有哪里理解错的地方欢迎大家留言交流,如需转载请标明出处。
如果你没看懂一定是我讲的不好,欢迎留言,我继续努力。
手工码字码图码代码,如果有帮助到你的话留个赞吧,谢谢。
以上。