Python学习第七课(让界面布局舒适,是一个长久的工作)

  • 一入布局深似海,加一减一都很难
    • 基础知识
    • 尝试布局
    • 尝试好布局,感受下元素带来的不同
    • 改造主程序,细节还是要优化
    • 细节优化,细枝末节的参数
    • 第一个实例课程,就这么结束咯

一入布局深似海,加一减一都很难

上一课,我们最终实现了这个软件的界面显示和控制功能。

看起来,我们是实现了功能,但是有点乱七八糟的。
其实Python除了自己的tkinter库以外,还有QtPy等多种其他库,都可以实现界面显示。
相比Qtpy图形拖拽式的制作界面,tkinter好像显得不那么友好。
不过,对于我们这个结构简单的程序来说,也没啥难的。

基础知识

首先,我们在上一课中使用了label、scale、button等元素,同时吧这些元素都放进了main的frame框架中。
这节课,我们要尝试灵活使用frame框架,为我们的程序实现布局优化。因此,几个必须了解的知识点要熟悉。

  1. 元素部署在哪个框架中,整体位置随着框架移动
  2. 当元素体积大于框架时,框架会随着元素增大
  3. 框架在使用pack方法打包时,可以设置“top、left、right、bottom”四种排列效果
  4. 除了pack方法,还可以使用grid、place,每种方法都有相应的参数用来确定呈现位置,需要仔细尝试

尝试布局

首先,我们新建一个py,尝试一下布局。
由于过程比较坎坷,所以很多尝试过程没法复原。

from tkinter import *root = Tk()
root.geometry("800x500+400+400")top = Frame(root,height=100, width=800, bd=5, highlightthickness=1)
left = Frame(root,height=200, width=199, bd=5, highlightthickness=1)
right = Frame(root,height=200, width=599, bd=5, highlightthickness=1)
foot = Frame(root,height=100, width=800, bd=5, highlightthickness=1)toplabel = Label(top, text="这里是top", font=("宋体", 16, "bold"), bd="2", bg="YELLOW", height=3, width=100)
leftlabel = Label(left, text="这里是left", font=("宋体", 16, "bold"), bd="2", bg="red", height=20, width=20)
rightlabel = Label(right, text="这里是right", font=("宋体", 16, "bold"),bd="2", bg="green", height=15, width=70)
footlabel = Label(foot, text="这里是foot", font=("宋体", 16, "bold"), bd="2", bg="blue", height=3, width=100)toplabel.pack()
leftlabel.pack()
rightlabel.pack()
footlabel.pack()top.pack(side='top')
left.pack(side='left')
right.pack()
foot.pack()root.mainloop()

可以明确的是,我们在新建窗口时候输入的信息,是指代像素px
但是在label里的宽高,并不指像素,仔细读代码可以看到,上面程序里label里的宽、高,都不是依照像素的大小限定的,如果你要尝试其他布局,要小心这里。
运行结果如下:

尝试好布局,感受下元素带来的不同

这里我们得到了一个不错的布局方案,下面我们把主程序使用的元素带入现在布局中,尝试一下。

from tkinter import *root = Tk()
root.geometry("800x300+400+400")
root.title("双色球小程序")
v = StringVar()top = Frame(root, height=100, width=800, bd=5, highlightthickness=1, relief="flat")
Ltitle = Label(top, text="上一期()开奖结果: ", font=("宋体", 16, "bold"), width=100, bd="2", anchor="w")
LRed =  Label(top, text="红球:", font=("宋体", 12, "bold"), width=100, bd="2", fg="RED", anchor="w")
LBlue = Label(top, text="蓝球:", font=("宋体", 12, "bold"), width=100, bd="2", fg="BLUE", anchor="w")left = Frame(root,height=200, width=199, bd=5, highlightthickness=1, relief="raised")
LAnswer = Label(left, textvariable = v, font=("宋体", 12, "bold"), bd="2", height=15, width=20)
v.set("恭喜發財!")right = Frame(root,height=200, width=599, bd=5, highlightthickness=1, relief="ridge")
slred = Scale(right, from_=6, to=33, orient="horizontal", tickinterval=1, length=580, label="红球", font=("宋体", 10, "bold"), fg="RED", sliderlength="10", sliderrelief="flat", width="5")
slblue = Scale(right, from_=1, to=16, orient="horizontal", tickinterval=1, length=580, label="蓝球", font=("宋体", 10, "bold"),  fg="BLUE", sliderlength="10", sliderrelief="flat", width="5")foot = Frame(root,height=100, width=800, bd=5, highlightthickness=1)
b1 = Button(foot, text ="  生成  ", width=20)Ltitle.pack()
LRed.pack()
LBlue.pack()slred.pack()
slblue.pack()
LAnswer.pack()
b1.pack()top.pack(side='top')
left.pack(side='left')
right.pack()
foot.pack(side='bottom')root.mainloop()

虽然我们上一节中已经成功呈现了想要的布局方式,但是在实际应用时候,要根据每个不同控件的特性设置,这里是设置调整后的结果。

可以看到,每个Frame有不同的效果显示,大家可以根据兴趣尝试,这里尝试了3种不同的样式。
同时我们还发现一个问题,用于选球数的scale控件是不能调整高度的,所以,只好整体缩小。
好了,现在我们可以放进真实环境,改造主程序了。

改造主程序,细节还是要优化

好了,融入上一节课最后的代码主程序部分:

if __name__ == "__main__":root = Tk()root.geometry("800x300+400+400")root.title("双色球小程序")v = StringVar()code = getNum()check = checkUrl(code)top = Frame(root, height=100, width=800, bd=5, highlightthickness=1, relief="flat")Ltitle = Label(top, text="上一期("+code+")开奖结果: ", font=("宋体", 16, "bold"), width=100, bd="2", anchor="w")LRed =  Label(top, text="红球:"+str(check['red']), font=("宋体", 12, "bold"), width=100, bd="2", fg="RED", anchor="w")LBlue = Label(top, text="蓝球:"+str(check['blue']), font=("宋体", 12, "bold"), width=100, bd="2", fg="BLUE", anchor="w")right = Frame(root,height=200, width=599, bd=5, highlightthickness=1, relief="ridge")slred = Scale(right, from_=6, to=33, orient="horizontal", tickinterval=1, length=580, label="红球", font=("宋体", 10, "bold"), fg="RED", sliderlength="10", sliderrelief="flat", width="5")slblue = Scale(right, from_=1, to=16, orient="horizontal", tickinterval=1, length=580, label="蓝球", font=("宋体", 10, "bold"),  fg="BLUE", sliderlength="10", sliderrelief="flat", width="5")left = Frame(root,height=200, width=199, bd=5, highlightthickness=1, relief="raised")LAnswer = Label(left, textvariable = v, font=("宋体", 12, "bold"), bd="2", height=15, width=20, anchor="n")v.set("恭喜發財!")foot = Frame(root,height=100, width=800, bd=5, highlightthickness=1)b1 = Button(foot, text ="生成", command=runThis)Ltitle.pack()LRed.pack()LBlue.pack()slred.pack()slblue.pack()LAnswer.pack()b1.pack()top.pack(side='top')left.pack(side='left')right.pack()foot.pack(side='bottom')root.mainloop()

运行,并尝试一下!

成功!
爬虫模块正常
选球模块正常
生成按钮正常
结果显示正常……吗?只显示了5个球

细节优化,细枝末节的参数

好吧,分析原因。
应该是控件宽度被限制了之后,显示结果并没有实现自动换行。
这时我们根据现象去学习的时候,才知道,原来label控件还有两个不起眼的参数设置:

  1. wraplength,如果遇到内容较多,可以设置到多长的时候就自动换行
  2. justify,可以设置换行的对其方式,比如:左对齐left;
    好的,我们加上去:
 LAnswer = Label(left, textvariable = v, font=("宋体", 12, "bold"), bd="2", height=15, width=20, anchor="n", wraplength = 200, justify = 'left')

再试试

成功!
还是贴上完整代码,供大家学习:

#encoding: utf-8from urllib import request
from urllib import parse
from datetime import datetime
import random
import math
import json
import os
from tkinter import *def newRedBall():num = random.randint(1, 33)return numdef newBlueBall():num = random.randint(1, 16)return numdef newTicket(red, rn, blue, bn):while len(red) < rn:temp = newRedBall()if not(temp in red):red.append(temp)temp = 0red.sort()while len(blue) < bn:temp = newBlueBall()if not(temp in blue):blue.append(temp)temp = 0blue.sort()return(red, blue)def needTickets(rn, bn):n1 = math.factorial(rn)n2 = math.factorial(rn-6)n3 = math.factorial(6)n = (n1/n2/n3)*bnreturn ndef checkUrl(number):Request_URL = 'http://www.cwl.gov.cn/cwl_admin/kjxx/findKjxx/forIssue'From_Data = {'name' : 'ssq','code' : number}header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",'Referer': 'http://www.cwl.gov.cn/kjxx/ssq/'}From_Data = parse.urlencode(From_Data)req = request.Request(url = Request_URL, data = bytes(From_Data,encoding = 'utf-8'), headers = header)res = request.urlopen(req)str_json = res.read().decode('utf-8')myjson = json.loads(str_json)info = myjson['result']return(info[0])def getNum():time = datetime.now().isocalendar()day = datetime.today()if int(time[2]) == 1:num = int(time[1]-1)*3elif int(time[2]) == 2:num = int(time[1]-1)*3if day.hour >= 22 :num += 1elif int(time[2]) == 3:num = int(time[1])*3-2elif int(time[2]) == 4:num = int(time[1])*3-2if day.hour >= 22 :num += 1elif int(time[2]) == 5:num = int(time[1])*3-1elif int(time[2]) == 6:num = int(time[1])*3-1else:num = int(time[1])*3-1if day.hour >= 22 :num += 1if int(day.month) > 3:num -= 4elif int(day.month) > 10:num -= 2if num < 100:code = str(time[0]) + "0" + str(num)else:code = str(time[0]) + str(num)return(code)def runThis():jg = ""rn = slred.get()bn = slblue.get()red = []blue = []newTicket(red, rn, blue, bn)ticket = needTickets(rn, bn)jg = "红球:\n"  + str(red) + "\n蓝球:" + str(blue)jg +=  "\n您所选号码共需要:\n " + str(ticket) + " 注, \n金额: ¥" + str(ticket*2)v.set(jg)if __name__ == "__main__":root = Tk()root.geometry("800x300+400+400")root.title("双色球小程序")v = StringVar()code = getNum()check = checkUrl(code)top = Frame(root, height=100, width=800, bd=5, highlightthickness=1, relief="flat")Ltitle = Label(top, text="上一期("+code+")开奖结果: ", font=("宋体", 16, "bold"), width=100, bd="2", anchor="w")LRed =  Label(top, text="红球:"+str(check['red']), font=("宋体", 12, "bold"), width=100, bd="2", fg="RED", anchor="w")LBlue = Label(top, text="蓝球:"+str(check['blue']), font=("宋体", 12, "bold"), width=100, bd="2", fg="BLUE", anchor="w")right = Frame(root,height=200, width=599, bd=5, highlightthickness=1, relief="ridge")slred = Scale(right, from_=6, to=33, orient="horizontal", tickinterval=1, length=580, label="红球", font=("宋体", 10, "bold"), fg="RED", sliderlength="10", sliderrelief="flat", width="5")slblue = Scale(right, from_=1, to=16, orient="horizontal", tickinterval=1, length=580, label="蓝球", font=("宋体", 10, "bold"),  fg="BLUE", sliderlength="10", sliderrelief="flat", width="5")left = Frame(root,height=200, width=199, bd=5, highlightthickness=1, relief="raised")LAnswer = Label(left, textvariable = v, font=("宋体", 12, "bold"), bd="2", height=15, width=20, anchor="n", wraplength = 200, justify = 'left')v.set("恭喜發財!")foot = Frame(root,height=100, width=800, bd=5, highlightthickness=1)b1 = Button(foot, text ="生成", command=runThis)Ltitle.pack()LRed.pack()LBlue.pack()slred.pack()slblue.pack()LAnswer.pack()b1.pack()top.pack(side='top')left.pack(side='left')right.pack()foot.pack(side='bottom')root.mainloop()

哦对了,既然已经成型,我们可以在cmd中使用:

pip install pyinstaller

安装一个pyinstaller库,然后在通过

pyinstaller -F 程序名.py -w

把这段程序变成一个exe文件。
这时候在文件目录下的dist中(譬如我的)

E:\py\dist

就可以找到exe文件,发给朋友一起玩玩吧!

第一个实例课程,就这么结束咯

希望这个实例课程,能够给一些初学Python的同学带来帮助。
首先,我需要承认。自己的代码并不是那么好看,好的习惯是很重要的。
其次,学习就是要有阶段性成果,才能激励自己不断进步。

在这七节课的内容里,并不包含很深、很精的技巧,但是囊括的知识点可以支撑起我们做出一个包含多元素的可视化程序。

  1. 第一节课知识点,爬取静态页面,并实现代码块的基本选取
  2. 第二节课知识点,爬虫与API的互动,实现数据的定向发送和获取
  3. 第三节课知识点,分析情报并制作一个自动化脚本
  4. 第四节课知识点,模块化封装程序,让每个模块可以复用
  5. 第五节课知识点,整合思路,形成完整的程序,并且优化输出方式
  6. 第六节课知识点,将已经成型的程序转换为GUI界面
  7. 第七节课知识点,GUI界面布局的基本知识

基于现在的知识点,我们可以开拓下思路:
结合第一节课和第六、七课的内容,是否可以制作一个网上爬取今日段子的可视化小程序?
结合第二节课和第六、七课的内容,制作一个自动翻译单词的可视化小程序?
或者,在课程的这个程序的基础上,深度思考第三节课的办法,制作一个带分析功能的彩票生成器?
因为现在,只要对期数生成器稍加改造,就可以用一句循环语句,获得过去数期的结果了。
好了。课程到这里。
期待再见!
这个专栏的最终成果也打包在这里,如果你并不打算学习python,也可以拿去随便玩玩哦!

Python学习,第七课(灵活使用Frame,让布局更舒适)相关推荐

  1. Python学习第七课-元组字典集合

    Python学习第七课-元组&字典&集合 一.元组 1.1元组简介 1.2元组的拆包 1.3字符串拆包 1.4列表的拆包 1.5拆包练习 二.字典的简介 2.1介绍 2.2操作 三.字 ...

  2. Python学习第六课-列表

    Python学习第六课-列表 一.序列 1.1 概念 1.2分类 二.列表 2.1 概念 2.2 练习 三.切片 3.1 可切片对象的索引方式 3.2切片操作 3.3 练习 四.通用操作 4.1 序列 ...

  3. python列表和字典_2020/11/18 python学习第5课 列表和字典

    python学习第5课 列表和字典 课程目标 熟练掌握列表.字典中元素的增删改查 理解列表和字典的区别 课程难点 列表与字典增删改查的异同 正确使用切片,深刻理解切片时冒号左右数字的意义 课程知识点总 ...

  4. Python学习第三课-基本数据类型

    Python学习第三课-基本数据类型 一.基本概念 1.1表达式 1.2语句 1.3程序 1.4函数 内置函数 自定义函数 参数 返回值 二.标识符 2.1 关键字 2.2标识符概念 驼峰命名法 下划 ...

  5. Python编程学习第七课之Python的数据类型

    在没有接触编程以前,电脑通常是用来看视频.听音乐以及玩游戏的.在这个过程里面,计算机不仅仅可以进行数字计算,还可以处理我们的视频.音乐以及动画等各种各样生活中常见的数据,针对这些不同的数据,每种编程语 ...

  6. Python学习第001课--课后复习

    今日是学习python的第001课,本节课主要学习了编程语言的定义及计算机的硬件基础. 一.什么是编程语言?什么是编程? 语言是一个事物与另一个事物沟通的介质: 编程语言是程序员与计算机沟通的介质: ...

  7. 1、Python学习笔记第一课:python介绍

    python学习第一课 python介绍: 1.python是一种解释性,面向对象语言. 2.特点: (1):可读性强: (2):简洁,生产效率高: (3):面向对象: (4):免费和开源: (5): ...

  8. Python学习,第一课(基础知识,利用urllib库入门)

    Python学习第一课(不怕失败,爬虫就是要爬点东西回来) 基本知识 第一课,第一个小爬虫 锁定目标 导入需要的库 良好的习惯 开始干活,做好失败的准备. 失败是成功他娘,下一课一定要搞到数据. 基本 ...

  9. python 学习第七讲作业 2020-12-29

    作业: 代码: flag = True flag2 = True while flag:str1 = input('最近学习了吗?yes/no:')# 对输入结果进行判断if str1 =='yes' ...

最新文章

  1. asp mysql连接已重置,mysql-检查经典ASP中的连接是否正常
  2. Fragment:关于Avoid non-default constructors in fragments的错误
  3. 苹果传出放弃研发自动驾驶,因iPhone销量不佳收紧支出
  4. 01-移植AZPR SoC到Xilinx Aritix7 FPGA
  5. ifc文件解析java_IFC标准 IFCWALLSTANDARDCASE参数说明
  6. Flexsim国外视频教程
  7. 人生第一次和第二次车祸
  8. ACM模板-f_zyj.pdf
  9. Mac电池系统管理软件App Tamer好用吗?
  10. Backtrader:用feather格式股票数据代替tushare进行数据回测
  11. Python 百天读书笔记 | Python语言进阶 16-20day
  12. 硬盘分区MBR和GPT选哪个好?原来分个区还有这么多讲究!
  13. 【ACM-ICPC 2018 沈阳赛区网络预赛】I.Lattice's basics in digital electronics ---- 字典树
  14. Java 使用Virtual Serial Port Driver及Modsim32进行modbus-rtu协议模拟(从机)并使用java当做主机(Maven项目)进行从机信息获取及修改
  15. 计算机专业实训日志-python有关
  16. S32K程序,基于S32k144官方开发版 包含大部分驱动,和UDS程序,UDS服务需要自己改
  17. IDEA 启动项目报错 Error running ‘XXXApplication‘: No jdk for module ‘XXX‘
  18. 解决虚拟机中ubuntu无法识别U盘
  19. 丢弃法(dropout)
  20. 南邮 | 离散数学实验二:集合上二元关系性质判定的实现

热门文章

  1. 外挂制作之思路总结和基址与偏移量
  2. v4l2及gstreamer使用指南
  3. python 多列排序_python sorted多列排序
  4. STM32 PWM控制电机寄存器配置
  5. AD2019网络标号批量改名
  6. 3650M5 IMM 配置升级
  7. 随笔-vue项目引入axios
  8. springBoot 用户头像的修改并及时显示
  9. armbian linux装AdGuard Home 广告拦截反追踪
  10. Protobuf的奇怪问题解决--Expected top - level statement (e.g message)