python+tkinter仿制win10标准型计算器(中文版)完美教学

设定上层显示组件, label——可多行显示,不可复制,不可直接通过键盘更改文本内容

self.label = tkinter.Label(text_frame, font=(“loMa”, 14),

textvariable=self.upper_display, bd=0, anchor=“se”, bg=“LightGray”)

  • text_frame: label要放置的对象。我们要把label放置在text_frame框架中。

  • font:字体。里边第一个参数是字体样式,第二个参数是字体大小。

  • textvariable:绑定可变对象。这里我们绑定的是上显示屏,其类型是StringVar()。

  • bd:边框大小。因为我们上下显示屏要看成一个整体,所以不能有边框,这里设置为0。

  • anchor:图形放置的位置。"se"表示东南部。相当于放在右下角了。说到这东西我必须吐槽一下,label明明也有justify属性(对齐方式),我把它修改为向右对齐却一点用都没有还是会居中显示,而entry修改这个属性后又能向右对齐,这给我整无语了。

  • bg:背景色。我为什么用这个颜色呢,因为我win10计算器是在pycharm下打开的,刚好那时候就显示这个色,我就把计算器调成这个颜色了,结果win10计算器颜色会变…想改其他颜色可以参考一下这个老哥@笑待人生原创库 的图片。

另外,要想查看更多tkinter命令可以查阅一下这篇文章。

Python GUI 编程(Tkinter) | 菜鸟教程 | 菜鸟教程")

创建下显示屏entry

设定下层显示组件, entry———单行输入显示,可复制,可直接通过键盘更改文本内容

self.entry = tkinter.Entry(text_frame, font=(“loMa”, 34, “bold”),

textvariable=self.lower_display, bd=0,

cursor=“circle”, justify=“right”, bg=“LightGray”)

这里的参数与label大致相似不再过多解释,在font参数那里多加了“bold”参数,表示加粗字体。下方参数多了个cursor表示鼠标图标,当我们将鼠标放上下显示屏的时候他会变成圆圈。截图截不了鼠标,各位可以自己试下,还是挺好看的。

放置显示屏

创建好显示屏后就要使用布局管理器将他们放入显示框架里面了,使用哪种布局呢?pack?虽然pack很方便,但是这里用不得pack。因为entry没有高度height属性,如果直接使用pack放置的话entry的高度会使用默认高度,很可能达不到你想要的结果。而place布局可以克服这一点,他可以自定义控件初始位置和大小,因此我们选用place布局管理器对上下显示屏进行布局。虽然label有高度属性,但是我们知道,布局管理器在同一容器里面只能使用一种,否则会报错,所以我们就统一使用place布局,并在里边设置起始位置和大小。

设定组件的放置位置及大小, entry没有高度这个属性,而默认高度显示不够美观,因为place布局可以自定义组件的高宽度,所以采用place布局

self.label.place(x=1, y=10, width=359, height=70)

self.entry.place(x=1, y=50, width=359, height=120)

x轴方向稍微空出一个像素会显得柔和些,不会那么突兀。

2.4创建按键框架

定义button_frame方法以及button_frame框架,将其放入到win窗口中的下部分。

按键

def button_frame(self):

button_frame = tkinter.Frame(self.win, width=370, height=270)

button_frame.pack(side=“bottom”)

将方法添加到init里面

self.text_frame()

2.5放置按钮

思路

遍历排列好的按钮字符串,定义行变量和列变量记录该按钮的行列值,列的值每满4个就要清零,行的值就要加一。然后使用grid布局将这些按钮根据此时行列值放置到按钮框架里面。放置的过程同时要绑定事件。事件下一小节会讲,这里就听一下概念就好。

确定按键顺序

我们根据计算器按键的顺序用一个按钮字符串存储起来,因为我们使用了中文字符,有时候一个按键的长度不为1,为了识别长度大于1的情况,我就用了花括号将按钮长度大于1的按钮名括起来。遍历时就能通过识别左右括号来确定里面按钮的值了。而长度为1的按钮直接添加到按钮框架即可。计算器按钮的布局是典型的二维表布局,所以使用grid布局管理器。先初始化变量。

设定计算器按键的顺序, 当按键名称长度大于一时用花括号括起来,方便后续判断

button_str = “%{CE}{清零}{删除}{求倒数}{求平方}{开根号}{除/}789{乘*}456{减-}123{加+}{相反数}0{小数点.}{等于=}”

ind = 0

row = 0

col = 0

length = len(button_str)

按钮放置与事件绑定

定义st变量记录按钮名称,遍历字符串,如果遇到左花括号,则在该位置使用index寻找右花括号的索引值。找离左括号最近的右括号,所以要设置查找的起始索引。找到后右花括号的位置就能使用切片获取按钮的值了,获取完值后索引移动到右花括号的位置(因为执行完一次while索引都会加1,所以就不用移动到下一个按钮的位置)。如果没有花括号则按钮名长度就是1,直接添加即可。

设置完按钮属性后将按钮放入按钮框架中,同时对按钮绑定事件,绑定事件的bind方法里面有两个参数,第一个参数是事件动作,第二个是事件对象。按钮发生相应的事件动作后,将会调用绑定的事件对象(函数)。

常见的事件动作有

  • 点击鼠标左键

  • 点击鼠标右键

  • 按下’A’键('A’可换其他按键)

  •   双击鼠标左键

每次放置后行列值都要发生相应的变化。

while ind < length:

当遇到花括号时(名称长度大于一),按键名为花括号里边的元素

if button_str[ind] == “{”:

找到离该左花括号最近的右花括号

end = button_str.index(‘}’, ind)

st = button_str[ind + 1:end]

指针移动到右花括号位置

ind = end

当名称长度为1时

else:

st = button_str[ind]

设置按钮属性

button = tkinter.Button(button_frame, text=st, font=(“loMa”, 14),

width=8, height=2)

按钮绑定事件click_button_event,当鼠标左键单击按钮时触发该事件

button.bind(“”, self.click_button_event)

使用grid网格布局放置按钮

button.grid(row=row, column=col)

col += 1

每行放置四个按钮, 每满四个换一行

if col >= 4:

row += 1

col = 0

ind += 1

2.6★定义按钮事件

重点来了。因为所有的按钮都绑定了同一个事件,所以计算器的核心算法都在这个事件里面。

先定义按钮事件,事件必须带至少一个参数,这个参数默认名为event。

定义按钮事件

def click_button_event(self, event):

我们可以通过event获取按钮的相关信息如名称,位置等。这里我们必须要获取按键名称才能对各个情况进行判断。

获取当前点击的按钮名称

button_text = event.widget[“text”]

我们由浅入深,先从容易理解的情况开始。

清零

前面我们讲过,计算器其中一个缺陷就是"%“, “CE”, “清零"三个按钮功能等价。因为我不太明白”%”, "CE"的计算逻辑,所以我直接把他俩归并到清零功能上了。(已修复CE情况,CE功能相当于将下显示屏设为0)

我们在计算器进行一些计算后点击清零会发现下显示屏变为0,上显示屏不显示,相当于回到了初始状态,所以点击清零相当于对所有数据进行了初始化。我们就定义一个初始化方法,初始化数据。(该方法在按钮事件里面定义)

对各个数据初始化

def initialize():

self.lower_display.set(“0”)

self.upper_display.set(“”)

self.factor1 = “”

self.factor2 = “”

self.operator = “”

self.last_click = “”

于是第一种情况我们就考虑完成了。

如果点击的按钮名称为清零CE%其中的一个,那么我们就调用初始化方法。(代码已更新)

if button_text in “清零CE%”:

当点击按钮为"CE"时,我们下显示屏清零。但如果上一次点击是等于号的话我们进入一次新运算,要进行初始化。

if button_text == “CE” and self.last_click != “等于=”:

self.lower_display.set(“0”)

else:

initialize()

至于为什么规定等号就进入一次新运算?可先看到下面的等号分支部分。

删除

计算器删除功能无非就是删除前面输错数字,因此我们进行判断,如果上一次点击的是数字就对其删除,否则不作响应。特别地,当上一次点击是等号的时候,上显示屏清空值,使用set方法将上显示屏设为空就好了。删除的思路就是确定下显示屏删除后是否还有值,有值就直接删除,没有值的话就设为0。

也许有朋友会有这样的一个疑惑,进行一次计算:点击数字8,再点击+号,想输入7不就输不了了?现在下显示屏还是显示8,按照上面那个删除的思路,因为上一次点击是+号不是数字,所以删不了8…这您就别担心,我在前面的设计思路提过重显示这个词吧?现在下显示屏处于重显示状态,如果下次点击是数字的话,他会直接覆盖掉之前的数字8,所以直接点击7就可以了。

因此按钮的第二个情况分支就是

elif button_text == “删除”:

删除最后一个字符

if self.last_click in “0123456789小数点.”:

分析删除一个字符后的情况

text = self.lower_display.get()[:-1]

if len(text) == 0:

self.lower_display.set(“0”)

else:

self.lower_display.set(text)

如果上一次点击是等号,则需保留下方数据,清除上方数据

elif self.last_click == “等于=”:

self.upper_display.set(“”)

记录上一次点击按钮

我们每执行完一次事件,都要记录上一次点击按钮的值,就拿删除功能而言,他也要判断上一次点击按钮是否是数字才能进行相应的操作。而有些按钮不应该被记录,这些按钮分别是“删除清零CE%”,我称这些按钮为状态按钮,因为他们只改变了计算器的状态,不会参与任何计算。

为什么要这么做呢?我打个比方,输入一个1,再输入一个1,输入第二个1的时候会判断上一个输入是否是数字,如果是的话加在它后面变成11,如果不是的话覆盖掉前面的值,变成1。显然,现在下显示屏显示是11。现在我们点击删除键,因为删除一个字符后还有值,所以现在显示变为1。此时输入一个2,如果上一次点击记录的是删除键,那么因为它不是数字,所以下显示屏会覆盖掉前面的值,显示为2,而按我们的计算思路是删除1之后继续输入数字2应该要显示12才对的,因此删除键不能参与记录上一次点击,那样的话上一次点击的按钮依旧是数字,这样就解决了数据插入的问题。

因此在事件的末尾添加如下语句。

if button_text not in “删除清零CE%”:

self.last_click = button_text

而每执行完一次事件后下显示屏应该都要处于最新显示的状态。当输入数字的长度大于显示长度时应显示后面的数字。比如输入数字12345,而显示屏只能显示3个数,那么这时显示屏显示的数字是345。

每执行完一次后将光标移动到最后面位置(考虑到有时候会通过键盘输入某些字符)

self.entry.icursor(“end”)

当输入的文本长度大于文本框长度时会显示更近输入的内容

self.entry.xview(“end”)

虽然我没有完善键盘输入的功能,但我还是设置了每次执行完一次事件光标移动到尾部的过程,因为有时候吧,偶尔输入一两个数字,不输入其他的话还是可以的。

◆等于

这次先上代码再说明情况

elif button_text == “等于=”:

出现多次点击等号时保留因子二不变,让结果与因子二计算

if self.last_click != button_text:

仅在首次点击等号时记录因子二

self.factor2 = self.lower_display.get()

正常情况直接计算结果

if self.operator:

expression = self.factor1 + self.operator + self.factor2

非正常情况点击数字后直接点击等号,上层将显示如 “8=”

else:

expression = self.factor2

用因子一保存结果

try:

self.factor1 = formatting_data(eval(expression))

self.lower_display.set(self.factor1)

self.upper_display.set(expression + " = ")

except ZeroDivisionError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “0 不能作为除数!”)

initialize()

**思路:**首次点击等号时用因子2记录下显示屏数据。一般等号是在前面输入“数字1  运算符  数字2”之后出现的,输入等号后就用因子2记录数字2。然后组合字符串因子1, 运算符, 因子2,通过eval函数求解结果。然后在上显示屏显示计算过程,下显示屏显示结果。提到上下显示屏我再说一下。**下显示屏显示数值,也只显示数值。上显示屏显示运算过程。运算过程就只有两种情况“因子1  运算符”, “因子1 运算符 因子2 = 结果”。**正常输入表达式的话是有结果的,但少不了特殊情况,如果你就输入一个数按等于的话,表达式就是这个数,所以结果也是这个数。如果连续点击等号的话因子二的值不会变,还是第一次点击等号时数字2的值,所以连续点击会直接让结果与因子2相加。

另外,当0作为除数求表达式是我们要给出提示,因为0作除数时是无效输入。这里我使用了警告框,是tkinter下面的一个组件,需要提前导入。

import tkinter.messagebox

看一下提示效果。

哎,因为我这个等于号的算法设计的不够好,导致小等于号处处受到排挤,在其他分支都要额外考虑他的存在…怪难受的,都怪我。明明他跟加减乘除都是运算符,可结果只有它独自承担所有。

考虑到等号的特殊性,我们规定,每进行一次等号运算后,都将开始一轮新的计算,有时候还需要对数据进行初始化。

如何理解开始一轮新的计算?我们看一个早期BUG。

各位发现有啥不妥的地方了吗?好像没啥毛病是吧?其实这里就是细节的问题了,这里的运算符是上一次计算的运算符,如果我不要加号要减号呢?不要不行,这里必须要。也许有人会说在点根号之前点一下减号不就可以了吗?确实可以,但,我说过这是面向老板编程,老板偏不走寻常路怎么办?所以我们只能委屈自己,尽量符合他的要求,设计更加人性化一点。上面我们规定如果上一次点击是等号而下一次点击不是等号的话进入新一轮计算。那么这里我们就进行一次判断,如果对使用等号求出来的结果进行开根号时,需要初始化数据,仅保留开根号的结果,以该结果开始等待下一次计算。

那么,等于这条分支就完成了。

格式化数据****formatting_data(可直接使用round函数)

在上面的代码了出现了formatting_data的字样,这是我定义的一个方法,他是用来格式化表达式的值–保留若干位小数,并去0。

**思路:**接收一个整型或浮点型数(eval得出来的结果是整型或浮点型),使用format方法使其保留若干位小数。然后从后往前遍历这个数,如果小数点后是0的话就把他去掉,直到遇到不是0的数,或者除掉小数点后为止。而这个遍历操作我是另外定义了一个方法zero_suppression,实现去零操作。

zero_suppression:

去除所有小数点后以0结尾的数字,如3.50000 执行该方法后变成3.5

def zero_suppression(nums):

倒序遍历nums

for i in nums[::-1]:

if “.” in nums and i in “0.”:

nums = nums[:-1]

直到遇到小数点后的非0数或者没有小数点停止

else:

break

return nums

formatting_data:

对传进来的表达式的值进行格式化输出

def formatting_data(exp):

f = str(format(exp, ‘.6f’)) # 保留6位小数

f = zero_suppression(f)

return f

加减乘除

兄弟们我好想快点发布博客呀,写了好多天了都。

**思路:**我们看这个输入过程“数字1 运算符1 数字2 运算符2”,当第一次出现运算符时我们用因子1记录数字1,并记录此时运算符1,然后在上显示屏显示因子1和运算符1,下显示屏置于重显示状态。当第二次出现运算符时我们就用因子2记录数字2,并用eval求解“因子1 运算符1 因子2”的值,然后将值给因子1,再记录运算符2。因为没有等号所以不用初始化,重新执行上显示屏显示因子1和运算符,下显示屏置于重显示状态的语句。**特殊情况:**1. 连续点击运算符时,我们不执行赋值语句,仅记录运算符,并重新显示运算符。2. 0不可作为除数,当其作为除数时,我们要使用警告框给出提示。

elif button_text in “加+减-乘*除/”:

每点击一次加减乘除都会用因子一因子二记录运算符前的数值

如果上一次点击是运算符,这次还是运算符,我们不希望他让因子一加上因子二。因为可能出现点错了,需要更换符号的情况

if self.last_click not in “加+减-乘*除/等于=”:

如果因子1存在则说明是二次点击,此时用因子二记录后一个数值并得出结果

if self.factor1:

考虑当0作为除数的情况

try:

self.factor2 = self.lower_display.get()

expression = self.factor1 + self.operator + self.factor2

self.factor1 = formatting_data(eval(expression))

self.lower_display.set(self.factor1)

except ZeroDivisionError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “0 不能作为除数!”)

initialize()

提前结束,不执行下面语句

return

首次点击运算符用因子一记录数值

else:

self.factor1 = self.lower_display.get()

记录运算符

self.operator = " %s " % button_text[-1]

每点击一次运算符我们上方显示屏都应该有一定的反馈

self.upper_display.set(self.factor1 + self.operator)

到这里运算符分支就完成了。

求平方求倒数开根号相反数

因为他们的功能相似,所以我直接把他们放在一起了。在这部分就要考虑更多无效输入的情况了,比如0没有倒数,负数不能开根号等,另外,这里暂时只支持整数开根号,不支持小数。所以出现这些情况都要给用户一些相应的反馈,而我依旧是使用警告框。

**思路:**求平方相反数等的无非就对两个对象处理,要么因子1,要么因子2。区分因子1和因子2就是要看是否输入了运算符,怎么看呢?看上显示屏,上显示屏显示的是计算过程,里面包含因子1和运算符的信息。现在记录下显示屏的值,我使用num记录。四种操作都是对下显示屏的值进行计算,不会影响其他变量的值如,因子1,因子2,运算符的值都不会影响。

  • 求平方:num * num

  • 求倒数: 1 / num

  • 相反数:-num

  • 开根号:使用 pow函数求(num,1/2)的值。

求解过程要注意提示错误输入的信息,出现输入错误后还要对数据进行初始化。然后将结果交给formatting_data方法处理。

处理完数据后我们就要在上显示屏显示信息了。若我们对因子1操作,则上方直接显示求解过程,

过程描述为: 处理前的值 +  按钮值(求平方/求倒数/开根号/相反数)+ 处理后的值。若对因子2操作,因为此时上方已经显示了因子1 + 运算符了,所以我们要在上显示屏显示的末尾加上求解过程,而不是直接覆盖。

因为四个操作的显示内容格式一致,所以我定义了一个方法update用于更新上显示屏数据,当得到处理后的数据后直接调用该方法即可,期间定义了一个flag变量用于标记报错情况,如果出现报错后我们直接初始化,不执行更新上显示屏的方法。

update:

进行求倒数求平方开根号运算时更新上下方显示屏数据

def update(n, res):

对因子1进行求倒数求平方开根号运算时直接显示运算后的结果

if not self.operator or self.operator not in self.upper_display.get():

self.upper_display.set(" ( " + n + " " + button_text + “: )” + res)

剩下就是对因子2进行计算,对其进行求倒数求平方开根号计算时,需保留显示因子1及运算符再显示运算结果

else:

self.upper_display.set(

self.factor1 + self.operator

  • " ( " + n + " " + button_text + “: )” + res)

下方显示屏无论对谁计算都只显示结果

self.lower_display.set(res)

求平方分支代码:

elif button_text in “求平方求倒数开根号相反数”:

num = self.lower_display.get()

flag = True

if self.last_click == “等于=”:

因为我们规定输入等于号后将进入新一轮计算,所以我们记录完结果的值后就对数据初始化

initialize()

if button_text == “求平方”:

expression = float(num) * float(num)

result = formatting_data(expression)

elif button_text == “求倒数”:

try:

expression = 1 / float(num)

result = formatting_data(expression)

except ZeroDivisionError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “0 没有倒数!”)

result = 0

initialize()

flag = False

elif button_text == “相反数”:

expression = “-” + num

result = str(eval(expression))

开根号情况

else:

try:

if int(num) >= 0:

expression = pow(int(num), 1 / 2)

result = formatting_data(expression)

else:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “负数不能开根号哦!”)

initialize()

flag = False

except ValueError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “暂时只支持正整数开根号哦!”)

initialize()

flag = False

现在倒回来看一下我也忘了出现这个错误是什么情况,都怪我当初没备注,为了炫酷直接把错误信息放提示框上了,没有用中文表达,我错了…

except ZeroDivisionError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “0 cannot be raised to a negative power”)

initialize()

flag = False

if flag:

update(str(num), str(result))

不容易啊兄弟们,终于快写完了

数字0~9

之前老说重显示重显示,重显示算法怎么实现呢?其实重显示只是说的高级一点,容易理解一点,其实就是进行判断如果上一次点击是运算符,下一次点击是数字的话,就要舍弃之前的数值,重新输入数字。当然除了运算符还有开平方那些,就是因为它涉及的按钮比较广而且思路容易理解,所以我才放在后面

我们直接上代码,代码讲的很详细了。

elif button_text in “0123456789”:

若上次是运算符则应重新输入数字,

对数值进行求平方求倒数开根号后不使用运算符而直接输入数字要进行初始化

使用等号得出结果再重新输入数值时需对其进行初始化

当第一个数字为0时要覆盖0值

if self.last_click in “加+减-乘*除/等于=” or \

self.last_click in “求平方求倒数开根号” or \

self.lower_display.get() == “0”:

if self.last_click in “等于=求平方求倒数开根号”:

initialize()

self.lower_display.set(button_text)

如果上一次点击也为数字则直接将新值插入到字符串后面

不必考虑相反数何时点击的情况

elif self.last_click in “0123456789小数点.相反数”:

self.entry.insert(“end”, button_text)

数字分支搞定了!还 差 最 后 一 个 分 支!

好激动真的,写了三四天,终于要熬出头了。最后还差最后一个啥分支?

小数点

这次代码比较容易理解,稍微看下注释就行,我就不多解释了

elif button_text == “小数点.”:

仅在没有小数点的情况下才能添加小数点,否则不作响应

if ‘.’ not in self.lower_display.get():

如果要给等号得出的结果加上小数点的话要进行一次初始化,因为点击完等号后相当于开始了新一轮的计算

if “=” in self.upper_display.get():

num = self.lower_display.get()

initialize()

self.lower_display.set(“%s.” % num)

否则直接加上小数点

else:

self.entry.insert(“end”, button_text[-1])

2.7生成可执行文件

在pycharm 的Terminal终端输入命令

pip install pyinstaller

安装成功的话会提示successfully installed,因为我已经安装这个库了,所以不会出现这个提示。

安装完依赖库后,执行如下命令,即可生成可执行文件

pyinstaller -F -w main.py

  • -F:表示打包成.exe可执行文件

  • -w: 解决打包成功后运行exe文件闪退的问题

  • (附)-i: 指定要加载的图标路径

  • main.py: 表示代码所在的.py文件名

因为我没有使用-i 命令所以是使用默认的图标;mian.py指的是文件名,如下。

执行生成命令后,末尾提示completed successfully的字样说明生成成功了

我们复制这个目录在文件夹打开,找到dist文件夹,进入,即可看到生成的可执行文件。

3.完整代码


import tkinter

import tkinter.messagebox

class TkWindows:

def init(self):

创建窗口对象

self.win = tkinter.Tk()

设置窗口宽度,高度以及窗口初始位置 x 为小写字母x 第一个加号后面参数是x轴坐标,第二个参数是y轴坐标

self.win.geometry(“360x460+570+200”)

定义拉伸的最大尺寸

self.win.maxsize(width=360, height=460)

定义窗口名称

self.win.title(“李帅哥的标准型计算器”)

初始化数据

self.lower_display = None # 上显示屏

self.upper_display = None # 下显示屏

self.entry = None

self.label = None

self.operator = “” # 运算符

self.factor1 = “”

self.factor2 = “”

self.last_click = “” # 上一次点击

调用start方法

self.start()

进入消息循环

self.win = tkinter.mainloop()

构建start方法用于调用生成两个窗体容器, 一个窗体作为显示屏显示数据, 另一个窗体作为按钮用于接收数据

def start(self):

tkinter.messagebox.showinfo(“李帅哥温馨提示”, “千山万水总是情 给个关注行不行\n创作不易 我是李帅哥 咋们下期见”)

self.button_frame()

self.text_frame()

显示屏——双显

def text_frame(self):

text_frame = tkinter.Frame(self.win, width=360, height=190)

text_frame.pack(side=“top”)

定义上下层显示屏可变追踪对象用于及时更新数据

self.lower_display = tkinter.StringVar()

self.upper_display = tkinter.StringVar()

设定下层显示的初始值

self.lower_display.set(“0”)

设定下层显示组件, entry———单行输入显示,可复制,可直接通过键盘更改文本内容

self.entry = tkinter.Entry(text_frame, font=(“loMa”, 34, “bold”),

textvariable=self.lower_display, bd=0,

cursor=“circle”, justify=“right”, bg=“LightGray”)

设定上层显示组件, label——可多行显示,不可复制,不可直接通过键盘更改文本内容

self.label = tkinter.Label(text_frame, font=(“loMa”, 14),

textvariable=self.upper_display, bd=0,

anchor=“se”, bg=“LightGray”)

设定组件的放置位置及大小, entry没有高度这个属性,而默认高度显示不够美观,因为place布局可以自定义组件的高宽度,所以采用place布局

self.label.place(x=1, y=10, width=359, height=70)

self.entry.place(x=1, y=50, width=359, height=120)

self.label.pack(side=“top”)

self.entry.pack(side=“bottom”)

按键

def button_frame(self):

button_frame = tkinter.Frame(self.win, width=370, height=270)

button_frame.pack(side=“bottom”)

设定计算器按键的顺序, 当按键名称长度大于一时用花括号括起来,方便后续判断

button_str = “%{CE}{清零}{删除}{求倒数}{求平方}{开根号}{除/}789{乘*}456{减-}123{加+}{相反数}0{小数点.}{等于=}”

ind = 0

row = 0

col = 0

length = len(button_str)

while ind < length:

当遇到花括号时(名称长度大于一),按键名为花括号里边的元素

if button_str[ind] == “{”:

找到离该左花括号最近的右花括号

end = button_str.index(‘}’, ind)

st = button_str[ind + 1:end]

指针移动到右花括号位置

ind = end

当名称长度为1时

else:

st = button_str[ind]

设置按钮属性

button = tkinter.Button(button_frame, text=st, font=(“loMa”, 14),

width=8, height=2)

使用grid网格布局放置按钮

button.grid(row=row, column=col)

按钮绑定事件click_button_event,当鼠标左键单击按钮时触发该事件

button.bind(“”, self.click_button_event)

col += 1

每行放置四个按钮, 每满四个换一行

if col >= 4:

row += 1

col = 0

ind += 1

定义按钮事件

def click_button_event(self, event):

获取当前点击的按钮名称

button_text = event.widget[“text”]

去除所有小数点后以0结尾的数字,如3.50000 执行该方法后变成3.5

def zero_suppression(nums):

倒序遍历nums

for i in nums[::-1]:

if “.” in nums and i in “0.”:

nums = nums[:-1]

直到遇到小数点后的非0数或者没有小数点停止

else:

break

return nums

对传进来的表达式的值进行格式化输出

def formatting_data(exp):

f = str(format(exp, ‘.6f’)) # 保留6位小数

f = zero_suppression(f)

return f

对各个数据初始化

def initialize():

self.lower_display.set(“0”)

self.upper_display.set(“”)

self.factor1 = “”

self.factor2 = “”

self.operator = “”

self.last_click = “”

进行求倒数求平方开根号运算时更新上下方显示屏数据

def update(n, res):

对因子1进行求倒数求平方开根号运算时直接显示运算后的结果

if not self.operator or self.operator not in self.upper_display.get():

self.upper_display.set(" ( " + n + " " + button_text + “: )” + res)

剩下就是对因子2进行计算,对其进行求倒数求平方开根号计算时,需保留显示因子1及运算符再显示运算结果

else:

self.upper_display.set(

self.factor1 + self.operator

  • " ( " + n + " " + button_text + “: )” + res)

下方显示屏无论对谁计算都只显示结果

self.lower_display.set(res)

if button_text in “清零CE%”:

当点击按钮为"CE"时,我们下显示屏清零。但如果上一次点击是等于号的话我们进入一次新运算,要进行初始化。

if button_text == “CE” and self.last_click != “等于=”:

self.lower_display.set(“0”)

else:

initialize()

elif button_text == “删除”:

删除最后一个字符

if self.last_click in “0123456789小数点.”:

分析删除一个字符后的情况

text = self.lower_display.get()[:-1]

if len(text) == 0:

self.lower_display.set(“0”)

else:

self.lower_display.set(text)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

display.set(

self.factor1 + self.operator

  • " ( " + n + " " + button_text + “: )” + res)

下方显示屏无论对谁计算都只显示结果

self.lower_display.set(res)

if button_text in “清零CE%”:

当点击按钮为"CE"时,我们下显示屏清零。但如果上一次点击是等于号的话我们进入一次新运算,要进行初始化。

if button_text == “CE” and self.last_click != “等于=”:

self.lower_display.set(“0”)

else:

initialize()

elif button_text == “删除”:

删除最后一个字符

if self.last_click in “0123456789小数点.”:

分析删除一个字符后的情况

text = self.lower_display.get()[:-1]

if len(text) == 0:

self.lower_display.set(“0”)

else:

self.lower_display.set(text)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-oJYqvhmH-1713610911373)]

[外链图片转存中…(img-XqCVH8H7-1713610911373)]

[外链图片转存中…(img-YNdLoZVY-1713610911374)]

[外链图片转存中…(img-zWOjvAop-1713610911374)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值