请求为Python Tkinter计算器添加进制转换按钮及功能
Tkinter科学计算器进制转换功能实现方案
实现说明
- 在计算器顶部新增DEC、BIN、OCT、HEX四个进制选择按钮,点击时向显示框插入对应标识
- 操作流程:点击源进制按钮→输入对应进制的合法数字→点击目标进制按钮→按
=完成转换 - 输入验证:自动检查数字是否符合源进制规则,不符合则弹出错误提示
- 兼容原有计算功能:未输入进制标识时,保留原科学计算器的运算逻辑
修改后的完整代码
from tkinter import * from tkinter import filedialog import tkinter.messagebox import math root = Tk() root.geometry("650x450+300+300") # 调整窗口高度容纳新按钮行 root.title("Scientific Calculator") switch = None # 进制标识插入函数 def insert_base(base): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, base) # 验证数字是否符合对应进制规则 def validate_number(num_str, base): try: if base == "BIN": int(num_str, 2) elif base == "OCT": int(num_str, 8) elif base == "DEC": int(num_str, 10) elif base == "HEX": int(num_str, 16) return True except ValueError: return False # 进制转换逻辑 def convert_base(input_str): # 提取源进制、数字、目标进制 bases = ["BIN", "OCT", "DEC", "HEX"] base_indices = [] for base in bases: idx = input_str.find(base) if idx != -1: base_indices.append((idx, base)) # 确保有且只有两个进制标识 if len(base_indices) != 2: return None # 排序,第一个是源进制,第二个是目标进制 base_indices.sort() (src_idx, src_base), (dest_idx, dest_base) = base_indices num_str = input_str[src_idx+len(src_base):dest_idx] if not num_str: return None # 验证数字合法性 if not validate_number(num_str, src_base): return False # 转换为十进制,再转目标进制 decimal_num = int(num_str, {"BIN":2, "OCT":8, "DEC":10, "HEX":16}[src_base]) if dest_base == "BIN": return bin(decimal_num)[2:] # 去掉前缀0b elif dest_base == "OCT": return oct(decimal_num)[2:] # 去掉前缀0o elif dest_base == "DEC": return str(decimal_num) elif dest_base == "HEX": return hex(decimal_num)[2:].upper() # 大写输出 # 数字按钮逻辑 def btn1_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '1') def btn2_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '2') def btn3_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '3') def btn4_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '4') def btn5_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '5') def btn6_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '6') def btn7_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '7') def btn8_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '8') def btn9_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '9') def btn0_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, '0') # 十六进制字母按钮逻辑 def btnA_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'A') def btnB_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'B') def btnC_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'C') def btnD_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'D') def btnE_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'E') def btnF_clicked(): if disp.get() == '0': disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, 'F') # 运算按钮逻辑 def btnp_clicked(): pos = len(disp.get()) disp.insert(pos, '+') def btnm_clicked(): pos = len(disp.get()) disp.insert(pos, '-') def btnml_clicked(): pos = len(disp.get()) disp.insert(pos, '*') def btnd_clicked(): pos = len(disp.get()) disp.insert(pos, '/') def bl_clicked(): pos = len(disp.get()) disp.insert(pos, '(') def br_clicked(): pos = len(disp.get()) disp.insert(pos, ')') def sqr_clicked(): try: ans = float(disp.get()) ans = math.sqrt(ans) disp.delete(0, END) disp.insert(0, str(ans)) except Exception: tkinter.messagebox.showerror("Value Error", "Check your values and operators") def pow_clicked(): pos = len(disp.get()) disp.insert(pos, '**') def mod_clicked(): pos = len(disp.get()) disp.insert(pos, '%') def dot_clicked(): pos = len(disp.get()) disp.insert(pos, '.') def btneq_clicked(): try: input_str = disp.get().strip() # 先检查是否是进制转换格式 bases = ["BIN", "OCT", "DEC", "HEX"] has_bases = any(base in input_str for base in bases) if has_bases: result = convert_base(input_str) if result is None: tkinter.messagebox.showerror("格式错误", "请按照【源进制+数字+目标进制】格式输入") elif result is False: tkinter.messagebox.showerror("输入错误", "数字不符合源进制规范") else: disp.delete(0, END) disp.insert(0, result) else: # 保留原有计算逻辑 ans = eval(input_str) disp.delete(0, END) disp.insert(0, ans) except: tkinter.messagebox.showerror("Value Error", "Check your values and operators") # 删除按钮逻辑 def del_clicked(): pos = len(disp.get()) display = str(disp.get()) if display == '': disp.insert(0, '0') elif display == ' ': disp.insert(0, '0') elif display == '0': pass else: disp.delete(0, END) disp.insert(0, display[0:pos-1]) def btnc_clicked(*args): disp.delete(0, END) disp.insert(0, '0') # 文件读取逻辑 def dat_clicked(): file_path = filedialog.askopenfilename(filetypes=[('Text Files', '*.txt')]) if file_path: with open(file_path, 'r') as file: content = file.read().replace('\n', '') disp.delete(0, END) pos = len(disp.get()) disp.insert(pos, content) data = StringVar() disp = Entry(root, font="Verdana 20", fg="black", bg="mistyrose", bd=4, justify=RIGHT, insertbackground="#abbab1", cursor="arrow") disp.pack(expand=TRUE, fill=BOTH) # 新增进制按钮行 btnrow0 = Frame(root, bg="#000000") btnrow0.pack(expand=TRUE, fill=BOTH) dec_btn = Button(btnrow0, text="DEC", font="Segoe 18", relief=GROOVE, bd=0, command=lambda: insert_base("DEC"), fg="white", bg="#333333") dec_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) bin_btn = Button(btnrow0, text="BIN", font="Segoe 18", relief=GROOVE, bd=0, command=lambda: insert_base("BIN"), fg="white", bg="#333333") bin_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) oct_btn = Button(btnrow0, text="OCT", font="Segoe 18", relief=GROOVE, bd=0, command=lambda: insert_base("OCT"), fg="white", bg="#333333") oct_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) hex_btn = Button(btnrow0, text="HEX", font="Segoe 18", relief=GROOVE, bd=0, command=lambda: insert_base("HEX"), fg="white", bg="#333333") hex_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) # 原数字运算按钮行1 btnrow1 = Frame(root, bg="#000000") btnrow1.pack(expand=TRUE, fill=BOTH) mod_btn = Button(btnrow1, text="%", font="Segoe 21", relief=GROOVE, bd=0, command=mod_clicked, fg="white", bg="#333333") mod_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) btn1 = Button(btnrow1, text="1", font="Segoe 23", relief=GROOVE, bd=0, command=btn1_clicked, fg="white", bg="#333333") btn1.pack(side=LEFT, expand=TRUE, fill=BOTH) btn2 = Button(btnrow1, text="2", font="Segoe 23", relief=GROOVE, bd=0, command=btn2_clicked, fg="white", bg="#333333") btn2.pack(side=LEFT, expand=TRUE, fill=BOTH) btn3 = Button(btnrow1, text="3", font="Segoe 23", relief=GROOVE, bd=0, command=btn3_clicked, fg="white", bg="#333333") btn3.pack(side=LEFT, expand=TRUE, fill=BOTH) btnp = Button(btnrow1, text="+", font="Segoe 23", relief=GROOVE, bd=0, command=btnp_clicked, fg="white", bg="#333333") btnp.pack(side=LEFT, expand=TRUE, fill=BOTH) # 新增十六进制字母按钮行 btnrow1_5 = Frame(root, bg="#000000") btnrow1_5.pack(expand=TRUE, fill=BOTH) btnA = Button(btnrow1_5, text="A", font="Segoe 23", relief=GROOVE, bd=0, command=btnA_clicked, fg="white", bg="#333333") btnA.pack(side=LEFT, expand=TRUE, fill=BOTH) btnB = Button(btnrow1_5, text="B", font="Segoe 23", relief=GROOVE, bd=0, command=btnB_clicked, fg="white", bg="#333333") btnB.pack(side=LEFT, expand=TRUE, fill=BOTH) btnC = Button(btnrow1_5, text="C", font="Segoe 23", relief=GROOVE, bd=0, command=btnC_clicked, fg="white", bg="#333333") btnC.pack(side=LEFT, expand=TRUE, fill=BOTH) btnD = Button(btnrow1_5, text="D", font="Segoe 23", relief=GROOVE, bd=0, command=btnD_clicked, fg="white", bg="#333333") btnD.pack(side=LEFT, expand=TRUE, fill=BOTH) btnE = Button(btnrow1_5, text="E", font="Segoe 23", relief=GROOVE, bd=0, command=btnE_clicked, fg="white", bg="#333333") btnE.pack(side=LEFT, expand=TRUE, fill=BOTH) btnF = Button(btnrow1_5, text="F", font="Segoe 23", relief=GROOVE, bd=0, command=btnF_clicked, fg="white", bg="#333333") btnF.pack(side=LEFT, expand=TRUE, fill=BOTH) # 原数字运算按钮行2 btnrow2 = Frame(root) btnrow2.pack(expand=TRUE, fill=BOTH) bl_btn = Button(btnrow2, text=" ( ", font="Segoe 21", relief=GROOVE, bd=0, command=bl_clicked, fg="white", bg="#333333") bl_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) br_btn = Button(btnrow2, text=" ) ", font="Segoe 21", relief=GROOVE, bd=0, command=br_clicked, fg="white", bg="#333333") br_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) btn4 = Button(btnrow2, text="4", font="Segoe 23", relief=GROOVE, bd=0, command=btn4_clicked, fg="white", bg="#333333") btn4.pack(side=LEFT, expand=TRUE, fill=BOTH) btn5 = Button(btnrow2, text="5", font="Segoe 23", relief=GROOVE, bd=0, command=btn5_clicked, fg="white", bg="#333333") btn5.pack(side=LEFT, expand=TRUE, fill=BOTH) btn6 = Button(btnrow2, text="6", font="Segoe 23", relief=GROOVE, bd=0, command=btn6_clicked, fg="white", bg="#333333") btn6.pack(side=LEFT, expand=TRUE, fill=BOTH) btnm = Button(btnrow2, text="-", font="Segoe 23", relief=GROOVE, bd=0, command=btnm_clicked, fg="white", bg="#333333") btnm.pack(side=LEFT, expand=TRUE, fill=BOTH) # 原数字运算按钮行3 btnrow3 = Frame(root) btnrow3.pack(expand=TRUE, fill=BOTH) sqr_btn = Button(btnrow3, text=" √x ", font="Segoe 18", relief=GROOVE, bd=0, command=sqr_clicked, fg="white", bg="#333333") sqr_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) pow_btn = Button(btnrow3, text="x^y", font="Segoe 17", relief=GROOVE, bd=0, command=pow_clicked, fg="white", bg="#333333") pow_btn.pack(side=LEFT, expand=TRUE, fill=BOTH) btn7 = Button(btnrow3, text="7", font="Segoe 23", relief=GROOVE, bd=0, command=btn7_clicked, fg="white", bg="#333333") btn7.pack
相关产品推荐
相关产品推荐

