suneryzgg123 发表于 2023-5-18 14:54

新手自学python,写了一个计算器代码求大佬帮忙指正一下不足和可以继续修改的地方

本帖最后由 suneryzgg123 于 2023-5-18 17:15 编辑

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from playsound import playsound

class Calculator:
    def __init__(self, master):
      self.result = None   # 定义 'result' 属性
      self.master = master
      master.title("多功能计算器")
      master.resizable(width=False, height=False)
      master.config(bg='#000')

      # 显示屏
      self.screen = tk.Entry(master, width=35, font=('Digital-7', 18),
                               justify='right', bd=5, bg='#000', fg='#fff')
      self.screen.grid(row=0, column=0, columnspan=4, padx=5, pady=5)

      # 按钮字体
      button_font = ("Digital-7", 20)

      # 数字按钮
      self.create_number_button(7, 1, 1, button_font, '#fff', '#11b8b5')
      self.create_number_button(8, 1, 2, button_font, '#fff', '#11b8b5')
      self.create_number_button(9, 1, 3, button_font, '#fff', '#11b8b5')
      self.create_number_button(4, 2, 1, button_font, '#fff', '#11b8b5')
      self.create_number_button(5, 2, 2, button_font, '#fff', '#11b8b5')
      self.create_number_button(6, 2, 3, button_font, '#fff', '#11b8b5')
      self.create_number_button(1, 3, 1, button_font, '#fff', '#11b8b5')
      self.create_number_button(2, 3, 2, button_font, '#fff', '#11b8b5')
      self.create_number_button(3, 3, 3, button_font, '#fff', '#11b8b5')
      self.create_number_button(0, 4, 2, button_font, '#fff', '#11b8b5')

      # 运算符按钮
      self.create_operator_button('+', 1, 4, button_font, '#fff', '#fc5c65')
      self.create_operator_button('-', 2, 4, button_font, '#fff', '#fc5c65')
      self.create_operator_button('*', 3, 4, button_font, '#fff', '#fc5c65')
      self.create_operator_button('/', 4, 4, button_font, '#fff', '#fc5c65')

      # 特殊计算按钮
      self.create_special_button('C', 4, 1, button_font, '#fff', '#eb3b5a')
      self.create_special_button('=', 4, 3, button_font, '#fff', '#20bf6b')
      self.create_special_button('.', 4, 4, button_font, '#fff', '#ffb142')
      self.create_special_button('√', 5, 1, button_font, '#fff', '#ff9f43')
      self.create_special_button('^', 5, 2, button_font, '#fff', '#ff9f43')
      self.create_special_button('(', 5, 3, button_font, '#fff', '#4b6584')
      self.create_special_button(')', 5, 4, button_font, '#fff', '#4b6584')

      # 其他控件
      self.create_menu()
      self.create_status_bar()

      # 计算结果
      self.result = None

    def create_number_button(self, number, row, column, font, fg=None, bg=None):
      button = tk.Button(self.master, text=number, width=7, height=2,
                           font=font, fg=fg, bg=bg, command=lambda: (self.append_to_screen(number),playsound('click.wav')))
      button.bind('<Enter>', lambda event, txt=f'输入 "{number}"': self.show_tooltip(txt))
      button.bind('<Leave>', self.hide_tooltip)
      button.grid(row=row, column=column, padx=3, pady=3)
      button.config(bd=5, relief='raised')
      button.config(activebackground='#000', activeforeground=fg)

    def create_operator_button(self, operator, row, column, font, fg=None, bg=None):
      button = tk.Button(self.master, text=operator, width=7, height=2,
                           font=font, fg=fg, bg=bg, command=lambda: (self.append_to_screen(operator),playsound('click.wav')))
      button.bind('<Enter>', lambda event, txt=f'输入 "{operator}"': self.show_tooltip(txt))
      button.bind('<Leave>', self.hide_tooltip)
      button.grid(row=row, column=column, padx=3, pady=3)
      button.config(bd=5, relief='raised')
      button.config(activebackground='#000', activeforeground=fg)

    def create_special_button(self, special, row, column, font, fg=None, bg=None):
      button = tk.Button(self.master, text=special, width=7, height=2,
                           font=font, fg=fg, bg=bg, command=lambda: (self.special_calculation(special),playsound('click.wav')))
      button.bind('<Enter>', lambda event, txt=f'输入 "{special}"': self.show_tooltip(txt))
      button.bind('<Leave>', self.hide_tooltip)
      button.grid(row=row, column=column, padx=3, pady=3)
      button.config(bd=5, relief='raised')
      button.config(activebackground='#000', activeforeground=fg)

    def append_to_screen(self, value):
      # 清空结果
      if self.result is not None:
            self.screen.delete(0, tk.END)
            self.result = None
      self.screen.insert(tk.END, value)

    def special_calculation(self, operator):
      expression = self.screen.get()
      try:
            if operator == 'C':
                self.result = None
                self.screen.delete(0, tk.END)
            elif operator == '=':
                # 计算表达式的值
                result = eval(expression)
                self.screen.delete(0, tk.END)
                self.screen.insert(tk.END, result)
                self.result = result
            elif operator == '.':
                if '.' not in expression:
                  self.screen.insert(tk.END, '.')
            elif operator == '√':
                # 计算平方根
                result = eval(expression + '**0.5')
                self.screen.delete(0, tk.END)
                self.screen.insert(tk.END, result)
                self.result = result
            elif operator == '^':
                # 计算平方
                result = eval(expression + '**2')
                self.screen.delete(0, tk.END)
                self.screen.insert(tk.END, result)
                self.result = result
            elif operator == '(':
                self.screen.insert(tk.END, '(')
            elif operator == ')':
                self.screen.insert(tk.END, ')')
      except ZeroDivisionError:
            messagebox.showerror('错误', '除数不能为0')
      except SyntaxError:
            messagebox.showerror('错误', '输入不合法')

    def create_menu(self):
      menu = tk.Menu(self.master)
      self.master.config(menu=menu)

      file_menu = tk.Menu(menu)
      file_menu.add_command(label='退出', command=self.master.quit)

      help_menu = tk.Menu(menu)
      help_menu.add_command(label='关于', command=self.show_about)

      menu.add_cascade(label='文件', menu=file_menu)
      menu.add_cascade(label='帮助', menu=help_menu)

    def create_status_bar(self):
      self.status_bar = tk.Label(self.master, text='', bd=1, relief=tk.SUNKEN,
                                 anchor=tk.W, bg='#000', fg='#fff')
      self.status_bar.grid(row=6, column=0, columnspan=4, sticky='we')

      self.update_status_bar()

    def update_status_bar(self):
      if self.result is None:
            self.status_bar.config(text='')
      else:
            self.status_bar.config(text=f'结果:{self.result}')
      self.master.after(100, self.update_status_bar)

    def show_about(self):
      messagebox.showinfo('关于', '学习制作,不足之处求轻喷。')

    def show_tooltip(self, text):
      x = self.master.winfo_x() + self.master.winfo_width() + 5
      y = self.master.winfo_y() + self.master.winfo_height() - 30
      self.tooltip = tk.Toplevel()
      self.tooltip.overrideredirect(True)
      self.tooltip.geometry(f'+{x}+{y}')
      label = ttk.Label(self.tooltip, text=text)
      label.pack(ipadx=5, ipady=5, padx=5, pady=5)
      self.tooltip.attributes('-topmost', True)

    def hide_tooltip(self, event):
      self.tooltip.destroy()

root = tk.Tk()
calculator = Calculator(root)
root.mainloop()

qfxldhw 发表于 2023-5-19 13:42

你提供的计算器代码总体上看起来不错。然而,还有一些地方可以进行改进:

职责分离:目前,计算器的所有代码都集中在一个名为Calculator的类中。最好将逻辑代码和GUI代码分离到不同的类或函数中,以提高代码的可读性和可维护性。

魔法数字:代码中有一些用于按钮的行和列位置的魔法数字。最好将这些数字定义为常量或变量,以使代码更易理解。

错误处理:代码使用消息框处理除以零和语法错误。虽然这可以工作,但最好直接在屏幕上提供更具信息性的错误消息,或使用单独的错误标签显示错误。

声音播放:代码使用playsound库在按钮按下时播放点击声音。虽然这可能是一个不错的补充,但对于计算器来说并不是一个关键功能。如果该库对你的要求不是必需的,可以移除声音播放的代码。

使用eval():使用eval()来评估表达式在不受信任的环境中可能存在潜在危险。考虑使用更安全和更可控的方法来评估表达式,例如使用解析器或专门设计用于数学计算的库。

代码格式化:遵循PEP 8指南,确保一致的代码格式化。包括在操作符周围添加空格、一致的缩进和使用空行来分隔代码的逻辑部分。

通过解决这些问题,你可以改进计算器代码的结构、可用性和可维护性。

soulstyle 发表于 2023-5-29 09:51

这里有几点可以优化的地方:
1. 使用常量代替"魔术字符串",如:
python
BG_COLOR = '#000'
FG_COLOR = '#fff'
然后在后续代码中使用 BG_COLOR 和 FG_COLOR 代替硬编码的颜色值。这会使代码更清晰易读。
2. 为按钮添加类型枚举,如:
python
BUTTON_TYPE = {
    'NUMBER': 1,
    'OPERATOR': 2,
    'SPECIAL': 3
}
然后在创建按钮时传入对应的类型,这会使代码更加结构化。
3. 使用更合适的名字代替 button_font,如 NUMBER_FONT、`OPERATOR_FONT` 等。
4. 为特殊按钮的逻辑提取成方法,如:
python
def calculate(self, expression):
    try:
      result = eval(expression)
      self.screen.delete(0, tk.END)
      self.screen.insert(tk.END, result)
      self.result = result
    except ZeroDivisionError:
      messagebox.showerror('错误', '除数不能为0')
    except SyntaxError:
      messagebox.showerror('错误', '输入不合法')

# 然后在特殊按钮事件中调用
elif operator == '=':
    self.calculate(expression)
5. 为菜单和状态栏 extract 成私有方法 _create_menu() 和 _create_status_bar(),根据 Python 的风格规范,私有方法名以下划线开头。
6. 使用 ttk 模块代替 tk 模块,ttk 模块支持更多的样式和使界面更美观。
7. 添加注释来提高代码的可读性。
总之,通过给代码添加更意义的命名,提取重复逻辑,使用常量代替硬编码,并添加适当的注释可以大大提高这段代码的质量和可读性。

dsijie 发表于 2023-5-26 21:00

qfxldhw 发表于 2023-5-19 13:42
你提供的计算器代码总体上看起来不错。然而,还有一些地方可以进行改进:

职责分离:目前,计算器的所有 ...

快说是不是gpt 回答的

dinkins 发表于 2023-5-18 16:18

厉害,顶一个

csf2022 发表于 2023-5-18 16:52

厉害了 我的哥 我也想学 不知道 改怎么下手 纯小白 。。。大佬推荐一下 适合小白的课程呗么么哒

suneryzgg123 发表于 2023-5-18 17:18

想继续添加一些别的功能跟美化一下界面,但是能力有限完善不来,有大佬可以帮忙指点一二,谢谢{:301_1004:}

suneryzgg123 发表于 2023-5-19 15:34

qfxldhw 发表于 2023-5-19 13:42
你提供的计算器代码总体上看起来不错。然而,还有一些地方可以进行改进:

职责分离:目前,计算器的所有 ...

好的感谢{:301_993:}

chumolu 发表于 2023-5-21 15:46

厉害{:1_921:}厉害{:1_921:}

ilcxyz 发表于 2023-5-21 16:21

我也刚刚学习了做一个简单的Tk计算器,你的程序比我的漂亮多了。

Klock0828 发表于 2023-5-24 11:07

可以的可以的

wendao_lx 发表于 2023-5-24 11:39

收藏了先!!
页: [1] 2
查看完整版本: 新手自学python,写了一个计算器代码求大佬帮忙指正一下不足和可以继续修改的地方