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 ...
 
随机推荐
- 如何将运维的报警做成运营的报警--Java后端架构
			
转:http://mp.weixin.qq.com/s?__biz=MzI4OTU3ODk3NQ==&mid=2247483970&idx=1&sn=2a00acfb25f0c ...
 - 关于 header()前面 为什么不能有任何输出的问题
			
之前有个问题就是在header () 之前输出,并没有任何报错信息. header() 官网定义必须在任何实际输出之前调用,不管是普通的HTML标签,还是文件或PHP输出的空行,空格.在测试的时候发现 ...
 - 切片操作:MATLAB VS Python
			
切片操作:MATLAB VS Python 一.MATLAB 矩阵的拆分 1.冒号表达式: t = e1:e2:e3 e1表示初始值,e2为步长,e3为终止值(包括e3),产生一个从e1到e3,步长为 ...
 - [垂直化搜索引擎]lucene简介及使用
			
摘自:大型分布式网站架构-设计与实践
 - ztree的数据绑定
			
ztree用法(1)首先引用ztree的css和js <link type="text/css" rel="stylesheet" href=" ...
 - 【转载】SQL执行计划
			
要理解执行计划,怎么也得先理解,那各种各样的名词吧.鉴于自己还不是很了解.本文打算作为只写懂的,不懂的懂了才写. 在开头要先说明,第一次看执行计划要注意,SQL Server的执行计划是从右向左看的. ...
 - Hive建模
			
Hive建模 1.介绍 Hive作为数据仓库,同关系型数据库开发过程类似,都需要先进行建模,所谓建模,就是对表之间指定关系方式.建模在hive中大致分为星型.雪花型和星座型.要对建模深入理解,首先需要 ...
 - Python基础学习之集合
			
集合是一个无序.不重复的数据集合,它的主要作用如下: 去重:把一个列表变成集合,就可以去除重复的内容 关系测试:测试两组数据之间的交集.并集.差集等关系 集合常用的操作: #创建一个数值集合 s=se ...
 - UVA-147 Dollars---完全背包+打表
			
题目链接: https://vjudge.net/problem/UVA-147 题目大意: 给定11种面值分别为$100, $50, $20, $10, and $5 notes and $2, $ ...
 - openwrt定制管理
			
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qianguozheng/article/details/24673097 近期这个比較火,可是改了东 ...