• Python小试牛刀:GUI(图形界面)实现计算器UI界面(三)


    上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)-CSDN博客

    我坚信好的作品一定要经过不同工匠不断的雕琢。我知道我的项目代码还可以进一步优化(比如等号事件那里等),以及一些BUG进行修复,但我个人比较懒,就让大家勉为其难将就着看吧。倘若大家运行发现一些BUG,以及好的建议,欢迎在评论区发表指正,谢谢!

    回顾前两篇文章,第一篇文章主要实现了计算器UI界面如何布局,以及简单概述Python常用的GUI库。第二篇文章主要实现了计算器UI界面按钮组件与事件的交互,而在本篇文章则是实现计算器完整功能。

    运行结果:

    代码设计

    1. """
    2. 计算器
    3. """
    4. # 通配符'*'
    5. __all__ = ['main']
    6. # 计算器UI设计
    7. class CalculatorUI:
    8. import tkinter as tk
    9. from tkinter import font
    10. base = tk.Tk() # 新建窗口
    11. base.title('计算器') # 设置标题
    12. base.geometry("458x400") # 设置窗口像素大小
    13. # 全局变量
    14. labelData1 = tk.StringVar() # 标签数据
    15. labelData2 = tk.StringVar() # 标签数据
    16. # 设置字体样式
    17. setChineseFont = font.Font(family='Arial', size=20, weight='bold')
    18. setFont = font.Font(family='Helvetica', size=12, weight='bold')
    19. # 主框架
    20. mainFrame = tk.LabelFrame(base, text='标准', borderwidth=2, relief=tk.FLAT, font=setChineseFont)
    21. mainFrame.pack(expand=True)
    22. # 标签框架
    23. labelFrame = tk.Frame(mainFrame, borderwidth=2, relief=tk.GROOVE)
    24. labelFrame.grid(columnspan=4)
    25. # 标签
    26. showLabel1 = tk.Label(labelFrame, textvariable=labelData1, anchor='e', width=26, font=setChineseFont)
    27. showLabel1.pack()
    28. showLabel2 = tk.Label(labelFrame, textvariable=labelData2, anchor='e', width=26, font=setChineseFont)
    29. showLabel2.pack()
    30. # 删除按钮
    31. clear = tk.Button(mainFrame, text='C', width=10, height=2, font=setFont)
    32. clear.grid(row=1, column=0)
    33. # 退格按钮
    34. backSpace = tk.Button(mainFrame, text='⬅', width=10, height=2, font=setFont)
    35. backSpace.grid(row=1, column=1)
    36. # 余数(百分号)
    37. remainder = tk.Button(mainFrame, text='%', width=10, height=2, font=setFont)
    38. remainder.grid(row=1, column=2)
    39. # 除号
    40. division = tk.Button(mainFrame, text='➗', width=10, height=2, font=setFont)
    41. division.grid(row=1, column=3)
    42. # 7
    43. seven = tk.Button(mainFrame, text='7', width=10, height=2, font=setFont)
    44. seven.grid(row=2, column=0)
    45. # 8
    46. eight = tk.Button(mainFrame, text='8', width=10, height=2, font=setFont)
    47. eight.grid(row=2, column=1)
    48. # 9
    49. nine = tk.Button(mainFrame, text='9', width=10, height=2, font=setFont)
    50. nine.grid(row=2, column=2)
    51. # 乘号
    52. multiplication = tk.Button(mainFrame, text='✖', width=10, height=2, font=setFont)
    53. multiplication.grid(row=2, column=3)
    54. # 4
    55. four = tk.Button(mainFrame, text='4', width=10, height=2, font=setFont)
    56. four.grid(row=3, column=0)
    57. # 5
    58. five = tk.Button(mainFrame, text='5', width=10, height=2, font=setFont)
    59. five.grid(row=3, column=1)
    60. # 6
    61. six = tk.Button(mainFrame, text='6', width=10, height=2, font=setFont)
    62. six.grid(row=3, column=2)
    63. # 减法
    64. subtraction = tk.Button(mainFrame, text='➖', width=10, height=2, font=setFont)
    65. subtraction.grid(row=3, column=3)
    66. # 1
    67. one = tk.Button(mainFrame, text='1', width=10, height=2, font=setFont)
    68. one.grid(row=4, column=0)
    69. # 2
    70. two = tk.Button(mainFrame, text='2', width=10, height=2, font=setFont)
    71. two.grid(row=4, column=1)
    72. # 3
    73. three = tk.Button(mainFrame, text='3', width=10, height=2, font=setFont)
    74. three.grid(row=4, column=2)
    75. # 加法
    76. addition = tk.Button(mainFrame, text='➕', width=10, height=2, font=setFont)
    77. addition.grid(row=4, column=3)
    78. # 括号
    79. brackets = tk.Button(mainFrame, text='( )', width=10, height=2, font=setFont)
    80. brackets.grid(row=5, column=0)
    81. # 0
    82. zero = tk.Button(mainFrame, text='0', width=10, height=2, font=setFont)
    83. zero.grid(row=5, column=1)
    84. # 小数点.
    85. dit = tk.Button(mainFrame, text='.', width=10, height=2, font=setFont)
    86. dit.grid(row=5, column=2)
    87. # 等于
    88. equal = tk.Button(mainFrame, text='=', width=10, height=2, background='#00BFFF', font=setFont)
    89. equal.grid(row=5, column=3)
    90. # 按钮间距
    91. tk.Label(mainFrame, height=3, width=1).grid(row=1, column=4) # 行填充
    92. tk.Label(mainFrame, height=3, width=1).grid(row=2, column=4)
    93. tk.Label(mainFrame, height=3, width=1).grid(row=3, column=4)
    94. tk.Label(mainFrame, height=3, width=1).grid(row=4, column=4)
    95. tk.Label(mainFrame, height=3, width=1).grid(row=5, column=4)
    96. tk.Label(mainFrame, height=1, width=16).grid(row=6, column=1) # 列填充
    97. tk.Label(mainFrame, height=1, width=16).grid(row=6, column=3)
    98. # 初始化事件
    99. def initUI(event):
    100. # 0-9
    101. UI.zero.config(background='#f0f0f0') # 0
    102. UI.one.config(background='#f0f0f0') # 1
    103. UI.two.config(background='#f0f0f0') # 2
    104. UI.three.config(background='#f0f0f0') # 3
    105. UI.four.config(background='#f0f0f0') # 4
    106. UI.five.config(background='#f0f0f0') # 5
    107. UI.six.config(background='#f0f0f0') # 6
    108. UI.seven.config(background='#f0f0f0') # 7
    109. UI.eight.config(background='#f0f0f0') # 8
    110. UI.nine.config(background='#f0f0f0') # 9
    111. # 特殊字符
    112. UI.clear.config(background='#f0f0f0') # 删除
    113. UI.backSpace.config(background='#f0f0f0') # 退格
    114. UI.remainder.config(background='#f0f0f0') # 百分号/求余
    115. UI.division.config(background='#f0f0f0') # 除号
    116. UI.multiplication.config(background='#f0f0f0') # 乘号
    117. UI.subtraction.config(background='#f0f0f0') # 减号
    118. UI.addition.config(background='#f0f0f0') # 加号
    119. UI.equal.config(background='#00BFFF') # 等于
    120. UI.brackets.config(background='#f0f0f0') # 括号
    121. UI.dit.config(background='#f0f0f0') # 小数点
    122. # 鼠标在组件上的焦点事件
    123. # 0-9
    124. # 0
    125. def zeroButton_1(event):
    126. UI.zero.config(background='pink')
    127. def zeroKeyPress(event):
    128. UI.zero.config(state=tk.DISABLED, background='pink')
    129. UI.base.update()
    130. time.sleep(0.1)
    131. UI.zero.config(state=tk.NORMAL, background='#f0f0f0')
    132. zeroEvent(event)
    133. # 1
    134. def oneButton_1(event):
    135. UI.one.config(background='pink')
    136. def oneKeyPress(event):
    137. UI.one.config(state=tk.DISABLED, background='pink')
    138. UI.base.update()
    139. time.sleep(0.1)
    140. UI.one.config(state=tk.NORMAL, background='#f0f0f0')
    141. oneEvent(event)
    142. # 2
    143. def twoButton_1(event):
    144. UI.two.config(background='pink')
    145. def twoKeyPress(event):
    146. UI.two.config(state=tk.DISABLED, background='pink')
    147. UI.base.update()
    148. time.sleep(0.1)
    149. UI.two.config(state=tk.NORMAL, background='#f0f0f0')
    150. twoEvent(event)
    151. # 3
    152. def threeButton_1(event):
    153. UI.three.config(background='pink')
    154. def threeKeyPress(event):
    155. UI.three.config(state=tk.DISABLED, background='pink')
    156. UI.base.update()
    157. time.sleep(0.1)
    158. UI.three.config(state=tk.NORMAL, background='#f0f0f0')
    159. threeEvent(event)
    160. # 4
    161. def fourButton_1(event):
    162. UI.four.config(background='pink')
    163. def fourKeyPress(event):
    164. UI.four.config(state=tk.DISABLED, background='pink')
    165. UI.base.update()
    166. time.sleep(0.1)
    167. UI.four.config(state=tk.NORMAL, background='#f0f0f0')
    168. fourEvent(event)
    169. # 5
    170. def fiveButton_1(event):
    171. UI.five.config(background='pink')
    172. def fiveKeyPress(event):
    173. UI.five.config(state=tk.DISABLED, background='pink')
    174. UI.base.update()
    175. time.sleep(0.1)
    176. UI.five.config(state=tk.NORMAL, background='#f0f0f0')
    177. fiveEvent(event)
    178. # 6
    179. def sixButton_1(event):
    180. UI.six.config(background='pink')
    181. def sixKeyPress(event):
    182. UI.six.config(state=tk.DISABLED, background='pink')
    183. UI.base.update()
    184. time.sleep(0.1)
    185. UI.six.config(state=tk.NORMAL, background='#f0f0f0')
    186. sixEvent(event)
    187. # 7
    188. def sevenButton_1(event):
    189. UI.seven.config(background='pink')
    190. def sevenKeyPress(event):
    191. UI.seven.config(state=tk.DISABLED, background='pink')
    192. UI.base.update()
    193. time.sleep(0.1)
    194. UI.seven.config(state=tk.NORMAL, background='#f0f0f0')
    195. sevenEvent(event)
    196. # 8
    197. def eightButton_1(event):
    198. UI.eight.config(background='pink')
    199. def eightKeyPress(event):
    200. UI.eight.config(state=tk.DISABLED, background='pink')
    201. UI.base.update()
    202. time.sleep(0.1)
    203. UI.eight.config(state=tk.NORMAL, background='#f0f0f0')
    204. eightEvent(event)
    205. # 9
    206. def nineButton_1(event):
    207. UI.nine.config(background='pink')
    208. def nineKeyPress(event):
    209. UI.nine.config(state=tk.DISABLED, background='pink')
    210. UI.base.update()
    211. time.sleep(0.1)
    212. UI.nine.config(state=tk.NORMAL, background='#f0f0f0')
    213. nineEvent(event)
    214. # 特殊字符
    215. # 删除
    216. def clearButton_1(event):
    217. UI.clear.config(background='pink')
    218. def clearKeyPress(event):
    219. UI.clear.config(state=tk.DISABLED, background='pink')
    220. UI.base.update()
    221. time.sleep(0.1)
    222. UI.clear.config(state=tk.NORMAL, background='#f0f0f0')
    223. clearEvent(event)
    224. # 退格
    225. def backSpaceButton_1(event):
    226. UI.backSpace.config(background='pink')
    227. def backSpaceKeyPress(event):
    228. UI.backSpace.config(state=tk.DISABLED, background='pink')
    229. UI.base.update()
    230. time.sleep(0.1)
    231. UI.backSpace.config(state=tk.NORMAL, background='#f0f0f0')
    232. backSpaceEvent(event)
    233. # 百分号/求余
    234. def remainderButton_1(event):
    235. UI.remainder.config(background='pink')
    236. def remainderKeyPress(event):
    237. UI.remainder.config(state=tk.DISABLED, background='pink')
    238. UI.base.update()
    239. time.sleep(0.1)
    240. UI.remainder.config(state=tk.NORMAL, background='#f0f0f0')
    241. remainderEvent(event)
    242. # 除号
    243. def divisionButton_1(event):
    244. UI.division.config(background='pink')
    245. def divisionKeyPress(event):
    246. UI.division.config(state=tk.DISABLED, background='pink')
    247. UI.base.update()
    248. time.sleep(0.1)
    249. UI.division.config(state=tk.NORMAL, background='#f0f0f0')
    250. divisionEvent(event)
    251. # 乘号
    252. def multiplicationButton_1(event):
    253. UI.multiplication.config(background='pink')
    254. def multiplicationKeyPress(event):
    255. UI.multiplication.config(state=tk.DISABLED, background='pink')
    256. UI.base.update()
    257. time.sleep(0.1)
    258. UI.multiplication.config(state=tk.NORMAL, background='#f0f0f0')
    259. multiplicationEvent(event)
    260. # 减号
    261. def subtractionButton_1(event):
    262. UI.subtraction.config(background='pink')
    263. def subtractionKeyPress(event):
    264. UI.subtraction.config(state=tk.DISABLED, background='pink')
    265. UI.base.update()
    266. time.sleep(0.1)
    267. UI.subtraction.config(state=tk.NORMAL, background='#f0f0f0')
    268. subtractionEvent(event)
    269. # 加号
    270. def additionButton_1(event):
    271. UI.addition.config(background='pink')
    272. def additionKeyPress(event):
    273. UI.addition.config(state=tk.DISABLED, background='pink')
    274. UI.base.update()
    275. time.sleep(0.1)
    276. UI.addition.config(state=tk.NORMAL, background='#f0f0f0')
    277. additionEvent(event)
    278. # 等于
    279. def equalButton_1(event):
    280. UI.equal.config(background='pink')
    281. def equalKeyPress(event):
    282. UI.equal.config(state=tk.DISABLED, background='pink')
    283. UI.base.update()
    284. time.sleep(0.1)
    285. UI.equal.config(state=tk.NORMAL, background='#00BFFF')
    286. equalEvent(event)
    287. # 括号
    288. def bracketsButton_1(event):
    289. UI.brackets.config(background='pink')
    290. def bracketsKeyPress(event):
    291. UI.brackets.config(state=tk.DISABLED, background='pink')
    292. UI.base.update()
    293. time.sleep(0.1)
    294. UI.brackets.config(state=tk.NORMAL, background='#f0f0f0')
    295. bracketsEvent(event)
    296. # 小数点
    297. def ditButton_1(event):
    298. UI.dit.config(background='pink')
    299. def ditKeyPress(event):
    300. UI.dit.config(state=tk.DISABLED, background='pink')
    301. UI.base.update()
    302. time.sleep(0.1)
    303. UI.dit.config(state=tk.NORMAL, background='#f0f0f0')
    304. ditEvent(event)
    305. # 组件背景颜色事件触发
    306. def widgetColor():
    307. # 初始化
    308. UI.base.bind('', initUI)
    309. UI.showLabel1.config(foreground='gray', background='white')
    310. UI.showLabel2.config(background='white')
    311. # 0-9
    312. UI.zero.bind('', zeroButton_1) # 0
    313. UI.one.bind('', oneButton_1) # 1
    314. UI.two.bind('', twoButton_1) # 2
    315. UI.three.bind('', threeButton_1) # 3
    316. UI.four.bind('', fourButton_1) # 4
    317. UI.five.bind('', fiveButton_1) # 5
    318. UI.six.bind('', sixButton_1) # 6
    319. UI.seven.bind('', sevenButton_1) # 7
    320. UI.eight.bind('', eightButton_1) # 8
    321. UI.nine.bind('', nineButton_1) # 9
    322. # 特殊字符
    323. UI.clear.bind('', clearButton_1) # 删除
    324. UI.backSpace.bind('', backSpaceButton_1) # 退格
    325. UI.remainder.bind('', remainderButton_1) # 百分号/求余
    326. UI.division.bind('', divisionButton_1) # 除号
    327. UI.multiplication.bind('', multiplicationButton_1) # 乘号
    328. UI.subtraction.bind('', subtractionButton_1) # 减号
    329. UI.addition.bind('', additionButton_1) # 加号
    330. UI.equal.bind('', equalButton_1) # 等于
    331. UI.brackets.bind('', bracketsButton_1) # 括号
    332. UI.dit.bind('', ditButton_1) # 小数点
    333. # 按钮按下
    334. UI.base.bind('', zeroKeyPress) # 0
    335. UI.zero.bind('', zeroEvent)
    336. UI.base.bind('', oneKeyPress) # 1
    337. UI.one.bind('', oneEvent)
    338. UI.base.bind('', twoKeyPress) # 2
    339. UI.two.bind('', twoEvent)
    340. UI.base.bind('', threeKeyPress) # 3
    341. UI.three.bind('', threeEvent)
    342. UI.base.bind('', fourKeyPress) # 4
    343. UI.four.bind('', fourEvent)
    344. UI.base.bind('', fiveKeyPress) # 5
    345. UI.five.bind('', fiveEvent)
    346. UI.base.bind('', sixKeyPress) # 6
    347. UI.six.bind('', sixEvent)
    348. UI.base.bind('', sevenKeyPress) # 7
    349. UI.seven.bind('', sevenEvent)
    350. UI.base.bind('', eightKeyPress) # 8
    351. UI.eight.bind('', eightEvent)
    352. UI.base.bind('', nineKeyPress) # 9
    353. UI.nine.bind('', nineEvent)
    354. UI.base.bind('', clearKeyPress) # 删除
    355. UI.base.bind('', clearKeyPress) # 删除
    356. UI.base.bind('', clearKeyPress) # 删除
    357. UI.clear.bind('', clearEvent)
    358. UI.base.bind('', backSpaceKeyPress) # 退格
    359. UI.backSpace.bind('', backSpaceEvent)
    360. UI.base.bind('', remainderKeyPress) # 百分号、求余
    361. UI.remainder.bind('', remainderEvent)
    362. UI.base.bind('', divisionKeyPress) # 除号
    363. UI.division.bind('', divisionEvent)
    364. UI.base.bind('', multiplicationKeyPress) # 乘号
    365. UI.base.bind('', multiplicationKeyPress) # 乘号
    366. UI.multiplication.bind('', multiplicationEvent)
    367. UI.base.bind('', subtractionKeyPress) # 减号
    368. UI.subtraction.bind('', subtractionEvent)
    369. UI.base.bind('', additionKeyPress) # 加号
    370. UI.base.bind('', additionKeyPress) # 加号
    371. UI.addition.bind('', additionEvent)
    372. UI.base.bind('', equalKeyPress) # 等号
    373. UI.base.bind('', equalKeyPress) # 等号
    374. UI.equal.bind('', equalEvent)
    375. UI.base.bind('', bracketsKeyPress) # 左括号
    376. UI.base.bind('', bracketsKeyPress) # 右括号
    377. UI.brackets.bind('', bracketsEvent)
    378. UI.base.bind('', ditKeyPress) # 小数点
    379. UI.dit.bind('', ditEvent)
    380. # 0 事件
    381. def zeroEvent(event):
    382. global labelShow2
    383. # 数字前面不能是右括号')'
    384. if ('原来是小瘪三'+labelShow2)[-1] in ')=':
    385. return
    386. labelShow2 += '0'
    387. '''
    388. # 补小数点
    389. if labelShow2 == '0' or labelShow2[-2] in '(+-×÷':
    390. labelShow2 += '.'
    391. '''
    392. UI.labelData2.set(labelShow2)
    393. UI.zero.config(activeforeground='gray')
    394. # 1 事件
    395. def oneEvent(event):
    396. global labelShow2
    397. # 数字前面不能是右括号')'
    398. if ('防止空字符'+labelShow2)[-1] in ')=':
    399. return
    400. labelShow2 += '1'
    401. UI.labelData2.set(labelShow2)
    402. UI.one.config(activeforeground='gray')
    403. # 2 事件
    404. def twoEvent(event):
    405. global labelShow2
    406. # 数字前面不能是右括号')'
    407. if ('什么字符都可以'+labelShow2)[-1] in ')=':
    408. return
    409. labelShow2 += '2'
    410. UI.labelData2.set(labelShow2)
    411. UI.two.config(activeforeground='gray')
    412. # 3 事件
    413. def threeEvent(event):
    414. global labelShow2
    415. # 数字前面不能是右括号')'
    416. if ('不影响代码'+labelShow2)[-1] in ')=':
    417. return
    418. labelShow2 += '3'
    419. UI.labelData2.set(labelShow2)
    420. UI.three.config(activeforeground='gray')
    421. # 4 事件
    422. def fourEvent(event):
    423. global labelShow2
    424. # 数字前面不能是右括号')'
    425. if ('虽然可以封装成函数'+labelShow2)[-1] in ')=':
    426. return
    427. labelShow2 += '4'
    428. UI.labelData2.set(labelShow2)
    429. UI.four.config(activeforeground='gray')
    430. # 5 事件
    431. def fiveEvent(event):
    432. global labelShow2
    433. # 数字前面不能是右括号')'
    434. if ('但是只有两行代码'+labelShow2)[-1] in ')=':
    435. return
    436. labelShow2 += '5'
    437. UI.labelData2.set(labelShow2)
    438. UI.five.config(activeforeground='gray')
    439. # 6 事件
    440. def sixEvent(event):
    441. global labelShow2
    442. # 数字前面不能是右括号')'
    443. if ('调用函数还是两行代码'+labelShow2)[-1] in ')=':
    444. return
    445. labelShow2 += '6'
    446. UI.labelData2.set(labelShow2)
    447. UI.six.config(activeforeground='gray')
    448. # 7 事件
    449. def sevenEvent(event):
    450. global labelShow2
    451. # 数字前面不能是右括号')'
    452. if ('索性来个自我介绍吧'+labelShow2)[-1] in ')=':
    453. return
    454. labelShow2 += '7'
    455. UI.labelData2.set(labelShow2)
    456. UI.seven.config(activeforeground='gray')
    457. # 8 事件
    458. def eightEvent(event):
    459. global labelShow2
    460. # 数字前面不能是右括号')'
    461. if ('我是周华2022'+labelShow2)[-1] in ')=':
    462. return
    463. labelShow2 += '8'
    464. UI.labelData2.set(labelShow2)
    465. UI.eight.config(activeforeground='gray')
    466. # 9 事件
    467. def nineEvent(event):
    468. global labelShow2
    469. # 数字前面不能是右括号')'
    470. if ('欢迎大家关注!'+labelShow2)[-1] in ')=':
    471. return
    472. labelShow2 += '9'
    473. UI.labelData2.set(labelShow2)
    474. UI.nine.config(activeforeground='gray')
    475. # 删除 事件
    476. def clearEvent(event):
    477. UI.clear.config(activeforeground='gray')
    478. global labelShow2, operator, operationData, bracketsFlag
    479. # 数据初始化
    480. bracketsFlag = 0
    481. labelShow2 = ''
    482. operator = []
    483. operationData = []
    484. UI.labelData2.set(labelShow2)
    485. # 退格 事件
    486. def backSpaceEvent(event):
    487. UI.backSpace.config(activeforeground='gray')
    488. global labelShow2
    489. # 在数据内退格
    490. if not operator:
    491. labelShow2 = labelShow2[:-1:]
    492. # 运算符退格
    493. elif operator and operationData:
    494. if labelShow2[-1] in '+-×÷%':
    495. operator.pop()
    496. operationData.pop()
    497. labelShow2 = labelShow2[:-1:]
    498. UI.labelData2.set(labelShow2)
    499. # 求余 事件
    500. def remainderEvent(event):
    501. UI.remainder.config(activeforeground='gray')
    502. global labelShow2
    503. # 首个字符不能出现百分号/求余
    504. if not labelShow2:
    505. return
    506. # 百分号前面不能出现运算符,除了右括号')'
    507. elif labelShow2[-1] in '+-×÷%(.=':
    508. return
    509. # 分割数据,获取数值和运算符
    510. elif not operator:
    511. operationData.append(labelShow2)
    512. elif operator:
    513. operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])
    514. operator.append('%')
    515. labelShow2 += '%'
    516. print(operator, operationData)
    517. UI.labelData2.set(labelShow2)
    518. # 除法 事件
    519. def divisionEvent(event):
    520. UI.division.config(activeforeground='gray')
    521. global labelShow2
    522. # 首个字符不能出现除号
    523. if not labelShow2:
    524. return
    525. # 除号前面不能出现运算符,除了右括号')'和百分号'%'
    526. elif labelShow2[-1] in '+-×÷(.=':
    527. return
    528. # 分割数据,获取数值和运算符
    529. elif not operator:
    530. operationData.append(labelShow2)
    531. elif operator:
    532. if labelShow2[-1] == '%':
    533. operationData[-1] += operator.pop()
    534. else:
    535. operationData.append(labelShow2.split(operationData[-1]+operator[-1])[-1])
    536. operator.append('÷')
    537. labelShow2 += '÷'
    538. print(operator, operationData)
    539. UI.labelData2.set(labelShow2)
    540. # 乘法 事件
    541. def multiplicationEvent(event):
    542. UI.multiplication.config(activeforeground='gray')
    543. global labelShow2
    544. # 首个字符不能出现乘号
    545. if not labelShow2:
    546. return
    547. # 乘号前面不能出现运算符,除了右括号')'和百分号'%'
    548. elif labelShow2[-1] in '+-×÷(.=':
    549. return
    550. # 分割数据,获取数值和运算符
    551. elif not operator:
    552. operationData.append(labelShow2)
    553. elif operator:
    554. if labelShow2[-1] == '%':
    555. operationData[-1] += operator.pop()
    556. else:
    557. operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])
    558. operator.append('×')
    559. labelShow2 += '×'
    560. print(operator, operationData)
    561. UI.labelData2.set(labelShow2)
    562. # 减法 事件
    563. def subtractionEvent(event):
    564. UI.subtraction.config(activeforeground='gray')
    565. addFlag = 1 # 添加运算符旗帜
    566. global labelShow2
    567. # 首字符出现减号,视为负号
    568. if not labelShow2:
    569. addFlag = 0 # 添加运算符旗帜
    570. # 减号前面不能出现运算符,除了括号'()'和百分号'%'
    571. elif labelShow2[-1] in '+-×÷.=':
    572. return
    573. # 分割数据,获取数值和运算符
    574. elif not operator and labelShow2[-1] not in '(':
    575. operationData.append(labelShow2)
    576. # 非首个数据
    577. elif operator and operationData:
    578. if labelShow2[-1] == '%':
    579. operationData[-1] += operator.pop()
    580. elif labelShow2[-1] == '(':
    581. addFlag = 0 # 添加运算符旗帜
    582. else:
    583. operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])
    584. else:
    585. addFlag = 0
    586. # 不保存运算符旗帜
    587. if addFlag:
    588. operator.append('-')
    589. print(operator, operationData)
    590. labelShow2 += '-'
    591. UI.labelData2.set(labelShow2)
    592. # 加法 事件
    593. def additionEvent(event):
    594. UI.addition.config(activeforeground='gray')
    595. addFlag = 1 # 添加运算符旗帜
    596. global labelShow2
    597. # 首字符出现加号,视为正号
    598. if not labelShow2:
    599. addFlag = 0 # 添加运算符旗帜
    600. # 加号前面不能出现运算符,除了括号'()'和百分号'%'
    601. elif labelShow2[-1] in '+-×÷.=':
    602. return
    603. # 分割数据,获取数值和运算符
    604. elif not operator and labelShow2[-1] not in '(':
    605. operationData.append(labelShow2)
    606. # 非首个数据
    607. elif operator and operationData:
    608. if labelShow2[-1] == '%':
    609. operationData[-1] += operator.pop()
    610. elif labelShow2[-1] == '(':
    611. addFlag = 0 # 添加运算符旗帜
    612. else:
    613. operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])
    614. else:
    615. addFlag = 0
    616. # 不保存运算符旗帜
    617. if addFlag:
    618. operator.append('+')
    619. print(operator, operationData)
    620. labelShow2 += '+' # 添加加号
    621. UI.labelData2.set(labelShow2)
    622. # 等于 事件
    623. def equalEvent(event):
    624. UI.equal.config(activeforeground='gray')
    625. global labelShow2, labelShow1
    626. labelShow1 = labelShow2 # 显示式子
    627. # 首字符不能输入等号
    628. if not labelShow2:
    629. return
    630. # 等号前不能出现的运算符,除了数字、右括号、百分号
    631. elif labelShow2[-1] in '+-×÷=.':
    632. return
    633. # 括号必须成对,
    634. elif len(re.findall(r'\(', labelShow2)) != len(re.findall(r'\)', labelShow2)):
    635. UI.labelData1.set(labelShow1+'=错误')
    636. UI.labelData2.set('括号不完整')
    637. return
    638. # 等号前面不能是不带括号的正数
    639. elif not operator and labelShow2[0] != '+' and not len(re.findall(r'\(', labelShow2)):
    640. return
    641. # 处理等号前面只有一个数时
    642. elif not operator or (labelShow2.strip('()+-')[-1] == '%' and len(operator) == 1 and operator[0] == '%'):
    643. subtractionNum = len(re.findall('-', labelShow2)) # 减号数
    644. # 查找百分号
    645. if labelShow2.strip('()+-')[-1] == '%':
    646. num = float(labelShow2.strip('()+-%')) / 100
    647. # 奇数负为负,偶数负为正
    648. if subtractionNum % 2:
    649. labelShow2 = str(-num)
    650. else:
    651. labelShow2 = str(num)
    652. elif labelShow2.strip('()+-')[-1] != '%':
    653. num = labelShow2.strip('()+-')
    654. # 奇数负为负,偶数负为正
    655. if subtractionNum % 2:
    656. labelShow2 = '-'+num
    657. else:
    658. labelShow2 = num
    659. # 复杂运算
    660. else:
    661. # 防止报错
    662. try:
    663. # 计算式子结果
    664. if resultEvent(event) == '求余错误' or resultEvent(event) == '除数错误':
    665. return
    666. except:
    667. UI.labelData1.set(labelShow1 + '=崩溃')
    668. UI.labelData2.set('抱歉,小算脑子烧坏了')
    669. return
    670. print(operator, operationData)
    671. labelShow1 += '='+labelShow2 # 显示计算的式子
    672. UI.labelData1.set(labelShow1)
    673. UI.labelData2.set(labelShow2)
    674. # 显示结果后删除存储的数据
    675. if operationData:
    676. operator.clear()
    677. operationData.clear()
    678. # 括号 事件
    679. def bracketsEvent(event):
    680. UI.brackets.config(activeforeground='gray')
    681. global labelShow2, bracketsFlag
    682. # 首字符出现左括号'('
    683. if not labelShow2:
    684. labelShow2 += '('
    685. # 左括号前面不能出现数字和小数点
    686. elif labelShow2[-1] in '+-×÷(%':
    687. labelShow2 += '('
    688. # 右括号前面必须是数字和右括号
    689. elif labelShow2[-1] not in '+-×÷%(.=' and len(re.findall(r'\(', labelShow2)) != len(re.findall(r'\)', labelShow2)):
    690. labelShow2 += ')'
    691. # 括号前面的百分号
    692. if ('出来单挑啊'+labelShow2)[-2] == '%':
    693. bracketsFlag += 1
    694. if bracketsFlag % 2:
    695. labelShow2 = labelShow2[:-1:]+'('
    696. else:
    697. labelShow2 = labelShow2[:-1:]+')'
    698. UI.labelData2.set(labelShow2)
    699. # 小数点 事件
    700. def ditEvent(event):
    701. UI.dit.config(activeforeground='gray')
    702. global labelShow2
    703. # 小数点开头或者小数点前面是运算符就补零
    704. if not labelShow2 or labelShow2[-1] in '(+-×÷%':
    705. labelShow2 += '0'
    706. # 小数点前面不能是右括号')'
    707. elif labelShow2[-1] in ')=':
    708. return
    709. # 限制小数点输入(一)
    710. elif not operator:
    711. if len(re.findall(r'\.', labelShow2)) >= 1:
    712. return
    713. # 限制小数点输入(二)
    714. elif operator and operationData:
    715. str = labelShow2.split(operationData[-1]+operator[-1])[-1]
    716. if len(re.findall(r'\.', str)) >= 1:
    717. return
    718. labelShow2 += '.'
    719. UI.labelData2.set(labelShow2)
    720. # 计算式子结果
    721. def resultEvent(event):
    722. global labelShow1, labelShow2, operator, operationData
    723. # 分割最后一个数
    724. if labelShow2[-1] == '%':
    725. operationData[-1] += operator.pop()
    726. else:
    727. operationData.append(labelShow2.split(operationData[-1] + operator[-1])[-1])
    728. print(operator, operationData)
    729. # 化繁为简,逐个括号化简
    730. while True:
    731. leftBrackets = [] # 左括号
    732. rightBrackets = [] # 右括号
    733. minBrackets = [] # 最小括号区间
    734. # 查找括号,并存储其索引号
    735. for i in range(len(operationData)):
    736. if '(' in operationData[i]:
    737. leftBrackets.append(i)
    738. elif ')' in operationData[i]:
    739. rightBrackets.append(i)
    740. # 找到最里层的括号
    741. for i in range(len(rightBrackets)):
    742. # 找到了
    743. if leftBrackets[-1] < rightBrackets[i]:
    744. left = leftBrackets[-1]
    745. right = rightBrackets[i]
    746. minBrackets.extend([left, right])
    747. break
    748. # 无括号式子设置
    749. if not minBrackets:
    750. minBrackets.extend([0, len(operationData)-1])
    751. bracketsNum = operationData[minBrackets[0]:minBrackets[1] + 1:]
    752. bracketsOperation = operator[minBrackets[0]:minBrackets[1]:]
    753. # 左括号数分割
    754. bracketsSplit = ''
    755. if re.findall(r'\(', bracketsNum[0]):
    756. bracketsSplit = bracketsNum[0].split('()')
    757. bracketsNum[0] = bracketsSplit[-1]
    758. # 化简括号内的式子
    759. while True:
    760. # 结束循环条件
    761. if not bracketsOperation:
    762. break
    763. # 排除运算错误(除数不为零、求余需整数)
    764. for i in range(len(bracketsOperation)):
    765. # 让百分号'%'参与运算
    766. for j in range(2):
    767. if '%' in bracketsNum[i+j]:
    768. bracketsNum[i+j] = str(float(bracketsNum[i+j].strip('()')[:-1:])/100)
    769. # 化简单个数的括号
    770. for j in range(2):
    771. if '(' in bracketsNum[i+j]:
    772. numSplit = len(bracketsNum[i+j].split('-'))-1
    773. # 根据负号数,判断数值正负
    774. if numSplit % 2 and numSplit >= 1:
    775. bracketsNum[i + j] = '-'+bracketsNum[i+j].strip('()+-')
    776. # 查找除号
    777. if bracketsOperation[i] == '÷':
    778. # 判断除数是否为零
    779. if float(bracketsNum[i+1].strip(')')) == 0:
    780. UI.labelData1.set(labelShow1 + '=错误')
    781. UI.labelData2.set('除数不能为零')
    782. return '除数错误'
    783. # 查找求余号
    784. elif bracketsOperation[i] == '%':
    785. # 判断两个数是否为整数
    786. for j in range(2):
    787. if re.findall(r'\.', bracketsNum[i+j]):
    788. UI.labelData1.set(labelShow1 + '=错误')
    789. UI.labelData2.set('求余必须为整数')
    790. return '求余错误'
    791. # 查找乘除求余(优先级高)
    792. if bracketsOperation[i] in '×÷%':
    793. # 计算两数之积
    794. if bracketsOperation[i] == '×':
    795. result = float(bracketsNum[i]) * float(bracketsNum[i+1].strip(')'))
    796. # 计算两数之商
    797. elif bracketsOperation[i] == '÷':
    798. result = float(bracketsNum[i]) / float(bracketsNum[i+1].strip(')'))
    799. # 计算两数之余
    800. elif bracketsOperation[i] == '%':
    801. result = float(bracketsNum[i]) % float(bracketsNum[i+1].strip(')'))
    802. # 修改括号区间的数据,并进入下一次循环查找
    803. bracketsNum.pop(i)
    804. bracketsNum.pop(i)
    805. bracketsOperation.pop(i)
    806. bracketsNum.insert(i, str(result))
    807. break
    808. # 查找加减(优先级低)
    809. elif bracketsOperation[i] in '+-':
    810. if '×' in bracketsOperation:
    811. continue
    812. elif '÷' in bracketsOperation:
    813. continue
    814. elif '%' in bracketsOperation:
    815. continue
    816. # 计算两数之和
    817. if bracketsOperation[i] == '+':
    818. result = float(bracketsNum[i]) + float(bracketsNum[i + 1].strip(')'))
    819. # 计算两数之差
    820. elif bracketsOperation[i] == '-':
    821. result = float(bracketsNum[i]) - float(bracketsNum[i + 1].strip(')'))
    822. # 修改括号区间的数据,并进入下一次循环查找
    823. bracketsNum.pop(i)
    824. bracketsNum.pop(i)
    825. bracketsOperation.pop(i)
    826. bracketsNum.insert(i, str(result))
    827. break
    828. # 替换数据之前要补括号
    829. leftBracketsNum = len(re.findall(r'\(', operationData[minBrackets[0]]))
    830. rightBracketsNum = len(re.findall(r'\)', operationData[minBrackets[1]]))
    831. if len(re.findall(r'\(', operationData[minBrackets[0]])) == len(re.findall(r'\)', operationData[minBrackets[0]]))\
    832. or len(re.findall(r'\(', operationData[minBrackets[1]])) == len(re.findall(r'\)', operationData[minBrackets[1]])):
    833. leftBracketsNum = rightBracketsNum = 0
    834. # 删除数据
    835. for i in range(minBrackets[0], minBrackets[1]+1):
    836. operationData.pop(minBrackets[0])
    837. for i in range(minBrackets[0], minBrackets[1]):
    838. operator.pop(minBrackets[0])
    839. # 化简一个括号后,根据左括号前正负号改变数值正负号
    840. if leftBracketsNum >= 1 and bracketsSplit[-2] == '-':
    841. if bracketsNum[0][0] == '-':
    842. bracketsNum[0] = bracketsNum[0][1::]
    843. else:
    844. bracketsNum[0] = '-' + bracketsNum[0]
    845. # 合并分割的左括号
    846. leftBracketsStr = ''
    847. if leftBracketsNum > rightBracketsNum:
    848. for i in range(len(bracketsSplit)-2):
    849. leftBracketsStr += bracketsSplit[i]+'('
    850. bracketsNum[0] = leftBracketsStr + bracketsNum[0]
    851. # 补左括号,并插入计算结果数据
    852. if leftBracketsNum > rightBracketsNum:
    853. operationData.insert(minBrackets[0], f"{bracketsNum[0]}")
    854. # 补右括号,并插入计算结果数据
    855. elif rightBracketsNum > leftBracketsNum:
    856. operationData.insert(minBrackets[0], f"{bracketsNum[0]}{')' * (rightBracketsNum-leftBracketsNum)}")
    857. # 删除两边多余的括号,并插入计算结果数据
    858. elif leftBracketsNum == rightBracketsNum:
    859. string = bracketsNum[0]
    860. # 计算左括号的负号数
    861. num = 0
    862. for i in bracketsSplit[:-2:]:
    863. if i == '-':
    864. num += 1
    865. # 消除括号
    866. if leftBracketsNum >= 1 and num:
    867. if num % 2:
    868. if string[0] == '+':
    869. string = '-' + string[1::]
    870. elif string[0] != '-':
    871. string = '-' + string
    872. else:
    873. if string[0] == '+':
    874. string = string[1::]
    875. operationData.insert(minBrackets[0], string)
    876. # 结束条件循环条件
    877. if not operator:
    878. labelShow2 = operationData[0]
    879. if ('one piece'+operationData[0])[-2::] == '.0':
    880. labelShow2 = operationData[0][:-2:]
    881. return
    882. # 全局变量
    883. import tkinter as tk
    884. import time, re
    885. UI = CalculatorUI() # 计算器UI设计
    886. operator = [] # 运算符
    887. operationData = [] # 运算数据
    888. labelShow1 = '' # 标签内容1
    889. labelShow2 = '' # 标签内容2
    890. bracketsFlag = 0 # 计数旗帜
    891. # 主函数
    892. def main():
    893. widgetColor() # 组件背景颜色改变
    894. UI.base.mainloop() # 保持窗口运行
    895. # 代码测试
    896. if __name__ == '__main__':
    897. main()
    898. else:
    899. print(f'导入{__name__}模块')

    作者:周华

    创作日期:2023/11/6

  • 相关阅读:
    【文本分类】《融合注意力和剪裁机制的通用文本分类模型》
    全面采集商品数据的电商API接口对接【支持5大主流电商平台】
    Pycharm配置Git以及Gitee实现代码管理(全网最详细)
    Python之第六章 内置容器 --- 集合
    网络安全应急响应典型案例-(DDOS类、僵尸网络类、数据泄露类)
    H3C(华三)交换堆叠/IRF配置实例
    R语言:多值提取到点
    [2022 广东省赛M] 拉格朗日插值 (多元函数极值 分治NTT)
    phpstudy开机自启
    springboot uniapp毕业设计-基于Uniapp+SSM实现的Android的网店系统实现的App
  • 原文地址:https://blog.csdn.net/zhouhua2022/article/details/134233982