我们在上一次课程中(python窗口编程-2:风格与布局 ),制作了完整的计算器窗口界面,只是那个窗口没有真正的功能,是点击任何按钮都会关闭。这一次,我们加入一些事件处理的功能,让它成为一个正常工作的窗口程序,并具备与普通的计算器一样的输入数字的操作能力。
事件处理的无限循环
为了避免点击按钮会关闭窗口,我们引入无限循环的事件处理:
while True: event, values = window.read() if event==sg.WIN_CLOSED: breakwindow.close()
使用这个代码,替换上次课程最后的两行代码。我们会看到,现在只有点击窗口右上角的“X”才能关闭窗口,点击其它的按钮虽然没有反应,但不会导致窗口的关闭了。
sg.WIN_CLOSED代表关闭窗口的按钮值,实际是None,但这样表达增强了代码的健壮性。如果有一天PySimpleGUI的新升级版决定修改关闭窗口的按钮值,我们的代码无须做任何修改(理应如此)。
凡是有无限循环的地方,都必须有退出循环的机制,否则程序无法终止。那将是一个很不友善的用户体验。这里的break语句,作用就是退出循环。
break不但用于while循环,也可以用于for循环。当遍历搜索一个数据时,找到数据并且无须继续搜索时,就可以用break退出循环。
数字键的处理
当按钮为数字的时候,我们这样表示
event in [str(i) for i in range(0,10)]:
这里又用到了列表生成式,我们在编程基础的课程中讲过(python语言基础-10:编程是一种艺术 ),含义是当事件为‘0’到‘9’几个数字的时候。
需求分析
很多软件产品的开发,并没有细致的需求描述,而是提供了一个参考原型。即:这个功能参考XXX进行开发。比如我们的计算器,按下按钮的反应究竟应该是怎样,来自对真实计算器的模拟。我们第一步的需求,只实现正常的数字输入功能。
计算器的操作,对很多朋友来说是很熟悉也很自然的。最好的操作界面设计,就应该是自然的,让用户无须培训,就能自然使用。我们用语言来描述一下。
- 计算器的输出框,永远不会是空白,它的默认状态就是一个0后面跟一个小数点。
- 输入数字,就开始增加整数的位数,但首位不会是0。
- 输入小数点,显示不会立刻改变,但后面再输入数字,就变成了小数的位,末尾可以是0。
本节课程,只实现前两个功能(的一部分)。
整数数位逻辑
为了实现功能2,让我们看一下基本的整数位逻辑。新输入的数字会改变原有数字的含义。新的数字占据个位,原来的个位变成十位,原来十位变成百位,依此类推。这个操作,在编程中,用一个简单的模式来表现:
Value= Value* 10+ NewDigit
程序语言,真的是一种语言,一句代码,就能把这个操作逻辑描述得清清楚楚。能够看懂并理解程序语言,这就是掌握编程的开始。
内部值与显示值的分离
我们注意到,计算器的显示,是数字后面跟着一个小数点。正常的数字转字符串不是这样的效果,我们必须人为地在后面添加一个小数点。
ShowStr= str(Value)+'.'
在这种操作逻辑下,将内部计算用的值与显示的效果分开是好的。它的好处体现在控制了复杂性的规模。编程活动不创造有形的物质,它的价值就在于控制复杂性。
更加明确的说,好的编程者的能力就体现在开发代码的全过程中始终把复杂性规模维持在自己能够控制的范围之内,并以此实现整体看起来相当复杂的功能逻辑。
(这里对比一下,交易的价值就在于控制风险。优秀的交易者,能够把交易风险限制在自己能够控制的范围之内,并以此为基础承担一般人整体看起来相当大的风险,从而获得风险利益。)
控制复杂性规模的一个方法,就是将可以分开的功能尽量分开。我们可以集中注意力思考如何通过按钮事件对内部值的改变时,可以不考虑显示的问题。而在处理显示的时候,只需集中注意力考虑它的静态状态,不用考虑它的变化。
(这与打仗的原理是一样的,在局部集中优势兵力对敌。)
最后贴一下局部实现的代码
value= 0while True: event, values = window.read() if event==sg.WIN_CLOSED: break if event == 'C': value= 0 elif event == '±': value= -value elif event in [str(i) for i in range(0,10)]: value= value* 10+ int(event) info= str(value)+'.' info=info[-12:] window['show'].update(info)window.close()
这里还有几个小的处理逻辑
- C按钮的处理,直接将内部值设置为0
- ±按钮的处理,内部值正负切换
- 为了美观起见,数字的显示只保留最后的12位
- 改变文本框的显示,用update函数,它提供了窗口界面的输出功能。
- 文本框的定位,用了它的名字(key),这里的key与前面课程中讲的key,功能含义完全不同,别弄混了。同名不同含义的问题,在自然语言和编程语言中都大量存在,这经常是引起各种混淆和争论的起因。我们从一开始就应当给予足够的重视。
课程小结
本节课程,介绍了如何开发一个真正的窗口应用,在窗口中响应输入,显示输出,完全脱离控制台的黑窗口。并讲了数位处理的基本逻辑,这在数学编程中是很常用的。
简单介绍了通过功能分离来控制编程复杂性的方法,控制复杂性将是贯穿编程的学习和实践的全过程,后面还会经常讲到。
朋友们可以自行尝试一下如何实现小数,下一次课程中再解说。