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真的是一个神奇的东西,界面还可以这样写!

不写了,太累了!下次要试试把自己写的东西发布成程序!

猜你喜欢

转载自www.cnblogs.com/LoveBeautiful/p/10168977.html