zoukankan      html  css  js  c++  java
  • 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真的是一个神奇的东西,界面还可以这样写!

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

  • 相关阅读:
    『C#基础』C#读写TXT文档
    『ExtJS』给 Panel Items 中的 Grid 更新数据
    『Spring.NET』常见错误整理(持续更新)
    『WPF』Timer的使用
    『WPF』使用 [Annotation] 注释来定制数据/实体类
    『WPF』DataGrid的使用
    vbs修改注册表
    利用C#重启远程计算机
    sql server2000创建表和修改表
    存储过程得到某个表的所有字段信息
  • 原文地址:https://www.cnblogs.com/LoveBeautiful/p/10168977.html
Copyright © 2011-2022 走看看