kivy学习二:做一个查询所在地区身份证前6位的小软件
经过半个月的尝试,终于成功,记录下来备查!
做完之后发现有很多的问题没有解决,请大佬多批评指教!
强烈建议:学习KIVY的查看官方文档
需要用的知识:
1、字典的相关知识
2、kivy的下拉列表(Drop-Down List)、textInput、按钮(button)、boxLayout
3、pickle模块的load()函数
ps:因为是小白,所以尽量用最简单的东西完成小程序,现在的目的是先让程序跑起来,以后再提升!
我的环境:pycharm、win7
一、我们先把一个kivy运行的必要框架写出来,新建一个main.py的文件。
import kivy
kivy.require('1.10.1') # 这是我kivy的版本号,官方标准写法
from kivy.app import App # 要求应用程序的基类继承自App类
class PersonalNumberApp(App):
def build(self):
pass
if __name__ == '__main__':
PersonalNumberApp().run()
详细请查看官方文档:https://kivy.org/doc/stable/guide/basic.html
二、新建一个PersonalNumber类,当然这个类名必须和你的程序名相同,因为Kivy以小写形式查找与App类同名的Kv文件,但是要记住首字母一定要大写。用的是BoxLayout,并把这个类名放在pass的位置。为什么这样,因为这是必须的。
import kivy
kivy.require('1.10.1') # 这是我kivy的版本号,官方标准写法
from kivy.app import App # 要求应用程序的基类继承自App类
from kivy.uix.boxLayout import BoxLayout
class PersonalNumber(BoxLayout)
pass
class MyApp(App):
def build(self):
PersonalNumber()
if __name__ == '__main__':
MyApp().run()
新手一定要注意字母的大小写以及导入模块,我就在这个地方弄了半天才搞懂
三、这个时候可以运行,但是什么也看不到,下面我们写可视化界面
我们预想的界面是这样的
新建一个personalnumber.kv的文件(注意这个文件的名必须与上面我们新建的类名相同,但是字母都是小写的)
用pycharm打开这个文件
这里我们要生成的是三行,其中第一行3列,我们先用按钮代替下拉列表
#:kivy 1.10.1
<PersonalNumber>: # 这里与我们新建的类名相同
BoxLayout: # 我们用的框架名
orientation: 'vertical' # 我们让界面显示三行
# 第一行我们也用BoxLayout框架,只不过是三列
BoxLayout: # 我们用的框架名
orientation: 'horizontal' # 我们让界面显示三列
# 先放三个按钮代替三个下拉列表框
Button:
text: '省下拉列表框'
font_name: 'simfang.ttf'
Button:
text: '市下拉列表框'
Button:
text: '县下拉列表框'
# 第二行的查询按钮
Button:
text: '查询'
# 第三行的输入框
TextInput:
text: '这里显示显示显示内容'
参考:https://kivy.org/doc/stable/api-kivy.uix.boxlayout.html
运行一下:
是不是很简单,很有意思!
四、载入字典内的数据
import pickle
dict_numbers = {} # 用于存储字典
with open('db.pk', 'rb') as f:
dict_numbers = pickle.load(f)
相关资源到这里下载:https://download.csdn.net/download/daxia5398/10871599
如果你是小白也没有C币,请给我留言,我传给你!
五、先做kivy的下拉列表(Drop-Down List),这个弄懂了,按钮和输入框都不是问题。
1、from kivy.uix.dropdown import DropDown
2、新建一个下拉列表类
class MyDropDown(DropDown):
pass
3、给第一行的三个按钮设一个ID,为以后我们访问它做准备;同时设置每个按钮的行为
Button:
id: btn1
text: '省下拉列表框'
font_name: 'simfang.ttf' #定义字体,我这里是把字体直接复制到程序的文件夹里
on_touch_down: root.province_list() # 按钮被按下,执行province_list(),显示所有的省,直辖市
Button:
id: btn2
text: '市下拉列表框'
font_name: 'simfang.ttf'
on_touch_down: root.city_list() # 按钮被按下,执行city_list(),显示省下拉列表中选中省包含的所有市
Button:
id: btn3
text: '县下拉列表框'
font_name: 'simfang.ttf'
on_touch_down: root.xian_list() # 按钮被按下,执行xian_list(),显示市下拉列表中选中市包含的所有县
刚才我们在第四点中已经把全国身份证前6位号码的数据读取到了dict_numbers这个字典里了,首先我们读取省列表,并以按钮的形式加载到按钮1这个下拉列表中,需要注意的是python访问KV里的小部件,可以通过小部件的ID进行访问,如self.ids.btn1这样。代码如下:
def province_list(self):
self.dropdown = MyDropDown()
for province in dict_numbers.keys():
province_btn = Button(text=province, size_hint_y=None, font_name='simfang.ttf', height=35)
province_btn.bind(on_release=lambda province_btn: self.dropdown.select(province_btn.text))
self.dropdown.add_widget(province_btn)
self.ids.btn1.fbind('on_release', self.dropdown.open)
self.dropdown.fbind('on_select', lambda instance, x: setattr(self.ids.btn1, 'text', x))
ps:这段代码放在PersonalNumber()类里面,具体可以参阅:https://kivy.org/doc/stable/api-kivy.uix.dropdown.html
我只是照猫画虎,半懂不懂,我们主要的任务是先把代码运行起来,呵呵!
接下来再把市、县的列表写出来,大同小异。
以下是main.py的内容:
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.uix.dropdown import DropDown
import pickle
from kivy.uix.button import Button
dict_numbers = {} # 用于存储字典
with open('db.pk', 'rb') as f:
dict_numbers = pickle.load(f)
class MyDropDown(DropDown):
pass
class PersonalNumber(BoxLayout):
def province_list(self):
self.dropdown = MyDropDown()
for province in dict_numbers.keys():
province_btn = Button(text=province, size_hint_y=None, font_name='simfang.ttf', height=35)
province_btn.bind(on_release=lambda province_btn: self.dropdown.select(province_btn.text))
self.dropdown.add_widget(province_btn)
self.ids.btn1.fbind('on_release', self.dropdown.open)
self.dropdown.fbind('on_select', lambda instance, x: setattr(self.ids.btn1, 'text', x))
def city_list(self):
self.provinces = self.ids.btn1.text
print(self.provinces)
self.dropdown = MyDropDown()
for city in dict_numbers[self.provinces]:
city_btn = Button(text=city, size_hint_y=None, font_name='simfang.ttf', height=35)
city_btn.bind(on_release=lambda city_btn: self.dropdown.select(city_btn.text))
self.dropdown.add_widget(city_btn)
self.ids.btn2.bind(on_release=self.dropdown.open)
self.dropdown.bind(on_select=lambda instance, x: setattr(self.ids.btn2, 'text', x))
def xian_list(self):
self.citys = self.ids.btn2.text
print(self.provinces, self.citys)
self.dropdown = MyDropDown()
self.dropdown.clear_widgets()
for xian in dict_numbers[self.provinces][self.citys]:
print(xian)
xian_btn = Button(text=xian, size_hint_y=None, font_name='simfang.ttf', height=35)
xian_btn.bind(on_release=lambda xian_btn: self.dropdown.select(xian_btn.text))
self.dropdown.add_widget(xian_btn)
self.ids.btn3.bind(on_release=self.dropdown.open)
self.dropdown.bind(on_select=lambda instance, x: setattr(self.ids.btn3, 'text', x))
class PersonalNumberApp(App):
def build(self):
return PersonalNumber()
if __name__ == '__main__':
PersonalNumberApp().run()
这时个运行会出现错误AttributeError: 'PersonalNumber' object has no attribute 'provinces'
我们需要对三个下拉列表框进行一下初始化
在PersonalNumber()类中加入两个变量
provinces = "北京市"
citys = '市辖区'
然后在KV文件中把btn1的text的值改为root.provinces,btn2的text的值改为root.citys
终于可以了。
六、写“查询”按钮的代码
老一套,先给查询按钮高个id:btn4,然后设置它的行为on_press:root.make_number()
在make_number()里面我们把三个下拉列表框中的标题(text)取出来,就可以得到该地区的身份证前6位数字
def make_number(self):
number_str = dict_numbers[self.ids.btn1.text][self.ids.btn2.text][self.ids.btn3.text]
print(number_str)
运行,错误KeyError: '市辖区'。怎么回事?
反复的看官方文档,最后的结论是:Kivy部件有生命周期,它的值不会及时的更新,具体原因我也看不懂,怎么办?还是看官方文档。(没有老师的小白就是这么的无耐,所有如果有条件的还是找个老师吧,太折磨人了。)
经过无数次主试验,终于成功了。
具体做法就是先初始化变量,利用StringProperty()进行自动更新。
不说了,我是小白,说也就不清,上代码。
还是不行,原因是没有在KV文件里把县的TEXT改过来(这里小白就不诉苦了,这个问题都自学了一个小时。总结:不细心害死人啊!)
七、把“查询”按钮得到的数据写到TextInput里面
经过上面的学习,这个相对来说就太容易了,代码就不写了。直接上全部代码。
main.py
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.uix.dropdown import DropDown
import pickle
from kivy.uix.button import Button
from kivy.properties import StringProperty
dict_numbers = {} # 用于存储字典
with open('db.pk', 'rb') as f:
dict_numbers = pickle.load(f)
class MyDropDown(DropDown):
pass
class PersonalNumber(BoxLayout):
provinces = StringProperty()
citys = StringProperty()
xians = StringProperty()
def __init__(self, **kwargs):
super(PersonalNumber, self).__init__(**kwargs)
self.provinces = "北京市"
self.citys = '市辖区'
self.xians = '长安区'
def province_list(self):
self.dropdown = MyDropDown()
for province in dict_numbers.keys():
province_btn = Button(text=province, size_hint_y=None, font_name='simfang.ttf', height=35)
province_btn.bind(on_release=lambda province_btn: self.dropdown.select(province_btn.text))
self.dropdown.add_widget(province_btn)
self.ids.btn1.fbind('on_release', self.dropdown.open)
self.dropdown.fbind('on_select', lambda instance, x: setattr(self.ids.btn1, 'text', x))
def city_list(self):
self.provinces = self.ids.btn1.text
print(self.provinces)
self.dropdown = MyDropDown()
for city in dict_numbers[self.provinces]:
city_btn = Button(text=city, size_hint_y=None, font_name='simfang.ttf', height=35)
city_btn.bind(on_release=lambda city_btn: self.dropdown.select(city_btn.text))
self.dropdown.add_widget(city_btn)
self.ids.btn2.bind(on_release=self.dropdown.open)
self.dropdown.bind(on_select=lambda instance, x: setattr(self.ids.btn2, 'text', x))
def xian_list(self):
self.citys = self.ids.btn2.text
print(self.provinces, self.citys)
self.dropdown = MyDropDown()
self.dropdown.clear_widgets()
for xian in dict_numbers[self.provinces][self.citys]:
print(xian)
xian_btn = Button(text=xian, size_hint_y=None, font_name='simfang.ttf', height=35)
xian_btn.bind(on_release=lambda xian_btn: self.dropdown.select(xian_btn.text))
self.dropdown.add_widget(xian_btn)
self.ids.btn3.bind(on_release=self.dropdown.open)
self.dropdown.bind(on_select=lambda instance, x: setattr(self.ids.btn3, 'text', x))
def make_number(self):
number_str = dict_numbers[self.ids.btn1.text][self.ids.btn2.text][self.ids.btn3.text]
print(number_str)
self.ids.text_out.text = number_str
class PersonalNumberApp(App):
def build(self):
return PersonalNumber()
if __name__ == '__main__':
PersonalNumberApp().run()
personalnumber.kv
#:kivy 1.10.1
<PersonalNumber>: # 这里与我们新建的类名相同
BoxLayout: # 我们用的框架名
orientation: 'vertical' # 我们让界面显示三行
# 第一行我们也用BoxLayout框架,只不过是三列
BoxLayout: # 我们用的框架名
orientation: 'horizontal' # 我们让界面显示三列
# 先放三个按钮代替三个下拉列表框
Button:
id: btn1
text: root.provinces
font_name: 'simfang.ttf' #定义字体,我这里是把字体直接复制到程序的文件夹里
on_touch_down: root.province_list() # 按钮被按下,执行province_list(),显示所有的省,直辖市
Button:
id: btn2
text: root.citys
font_name: 'simfang.ttf'
on_touch_down: root.city_list() # 按钮被按下,执行city_list(),显示省下拉列表中选中省包含的所有市
Button:
id: btn3
text: root.xians
font_name: 'simfang.ttf'
on_press: root.xian_list() # 按钮被按下,执行xian_list(),显示市下拉列表中选中市包含的所有县
# 第二行的查询按钮
Button:
id: btn4
text: '查询'
font_name: 'simfang.ttf'
on_press:root.make_number()
# 第三行的输入框
TextInput:
id: text_out
text: '这里显示显示显示内容'
font_name: 'simfang.ttf'
p s:这篇文章写了一天,感觉写文章也是件苦差事。但是也复习了一遍自己的所学。不足的是界面还是太难看,还需要继续的美化一下。这个就不写出来了!
总结:
1、自学真是有苦有甜。苦的是没人指点,走了很多的弯路,有时候一个小小的问题就要摸索很久;甜的是那种完成功能后的那种欣喜。
2、文档对于小白来说真是太不友好了,好多概念真是要命啊!
3、Kivy真的是一个神奇的东西,界面还可以这样写!
不写了,太累了!下次要试试把自己写的东西发布成程序!
kivy学习二:做一个查询所在地区身份证前6位的小软件的更多相关文章
- OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型
OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...
- 做一个牛XX的身份证号验证类(支持15位和18位)
原文:做一个牛XX的身份证号验证类(支持15位和18位) #region 是否合法的中国身份证号码 protected bool IsChineseID() { if (str.Length == 1 ...
- [ 原创 ]学习笔记-做一个Android音乐播放器是遇到的一些困难
最近再做一个安卓的音乐播放器,是实验室里学长派的任务,我是在eclipse上进行开发的,由于没有android的基础,所以做起来困难重重. 首先是布局上的困难 1.layout里的控件属性不熟悉 2. ...
- restql 学习二 几种查询模式
restql 提供了比较强大的查询处理. 支持的几种查询模式 基本查询,主要是单一映射资源的查询,(from,with,only,header,cache...) 并行查询,多个资源的同时查询,(对于 ...
- pipelinewise 学习二 创建一个简单的pipeline
pipelinewise 提供了方便的创建简单pipeline的命令,可以简化pipeline 的创建,同时也可以帮我们学习 生成demo pipeline pipelinewise init --n ...
- python flask框架学习(二)——第一个flask程序
第一个flask程序 学习自:知了课堂Python Flask框架——全栈开发 1.用pycharm新建一个flask项目 2.运行程序 from flask import Flask # 创建一个F ...
- Android Afinal框架学习(二) FinalActivity 一个IOC框架
框架地址:https://github.com/yangfuhai/afinal 相应的源代码: net.tsz.afinal.annotation.view.* FinalActivity Fina ...
- micronaut 学习 二 创建一个简单的服务
micronaut 提供的cli 很方便,我们可以快速创建具有所需特性的应用,以下是一个简单的web server app 创建命令 mn create-app hello-world 效果 mn c ...
- python web开发——django学习(二)第一个django网站运行成功
1.写message_form.html <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
随机推荐
- 温习SQL语句
作为一名使用C#语言开发人员,就很难逃脱与SQLSERVER打交道,虽说我们是开发人员,但我想说的是,对数据库的操作还是应该时不时的拿出来温习一番.下面那就是我见过的一道有趣的SQL题目,与你们一起分 ...
- IDEA 生成 JPA实体类
文章目录1.创建工程2.连接数据源3.生成`JPA`实体类4.生成实体类结果1.创建工程使用Maven来构建工程,为了简化创建步骤 创建一个新工程不包含任何Maven模板,[按需添加] 命名 Grou ...
- Eclipse+ADT+Android SDK 搭建安卓开发环境(转)
要求 必备知识 windows 7 基本操作. 运行环境 windows 7(64位); eclipse-jee-luna-SR2-win32(32位);ADT-23.0.4 下载地址 环境下载 最近 ...
- 【起航计划 013】2015 起航计划 Android APIDemo的魔鬼步伐 12 App->Activity->SetWallpaper 设置壁纸 WallpaperManager getDrawingCache使用
SetWallpaper介绍如何在Android获取当前Wallpaper,对Wallpaper做些修改,然后用修改后的图像重新设置Wallpaper.(即设置>显示>壁纸>壁纸的功 ...
- 【菜鸟学Linux】Cron Job定期删除Log(日志)文件
以前一直做Windows开发,近期的项目中要求使用Linux.作为小菜鸟一枚,赶紧买了一本经典书<鸟哥的Linux私房菜>学习.最近刚好有一个小任务 - 由于产品产生的Log很多,而且增长 ...
- C++常用字符串分割方法(转)
1.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...
- Java—数组和方法
数组 声明数组 数组类型[] 数组名;or 数据类型 数组名[]; 如:int[] scores; 分配空间 数组名 = new 数据类型[数组长度];如:scores = new int[5]; 以 ...
- 基于FPGA的VGA显示设计(一)
前言 FPGA主要运用于芯片验证.通信.图像处理.显示VGA接口的显示器是最基本的要求了. 原理 首先需要了解 : (1)VGA接口协议:VGA端子_维基百科 .VGA视频传输标准_百度 引脚1 RE ...
- Wampserver由橙变绿的解决过程
因为C盘的内存问题,就重装了win7系统,那么就面临着很对软件要重新进行安装,安装wampserver时,再次遇到了服务器的图标一直是橙色的而不变绿色,安装包地址: http://download.c ...
- C++学习之虚函数继承和虚继承
虚函数的定义要遵循以下重要规则: 1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行晚绑定的. 2.只有类的成员函 ...