专栏首页bit哲学院利用Python编写一个行业专用的小计算器

利用Python编写一个行业专用的小计算器

参考链接: 使用Python创建一个简单的计算器

前言:本文讲述的是如何利用python编程制作一个适用于指定行业的计算器,方便计算结果,涵盖的知识点由Python编写GUI界面程序,利用爬虫采集实时的汇率数据,将Python文件打包成可以单独运行的exe文件。 

首先,分析我们的需求,编写一个适用于指定行业的计算器,这里我们用到的计算公式很简单,就是淘宝提供的金石定价公式,如下图所示 

淘宝定价计算器 

这里可以看到这个计算公式还是蛮简单的,对于Python来说也就是一行代码的事,那么我们就开始着手写代码,首先搭建我们的页面布局,这里我们采用的是tkinter,这个框架在画GUI方面还是很简单方便的,首先给大家展示下我的最终布局,如下图所示 

最终样式 

其实也不是很好看,不过我已经尽我所能去美化了,其实功能很简单,就是几个输入框,两个按钮,点击计算按钮,获取输入框中的值,通过Python代码计算结果,最后将计算结果写入指定的输入框中,关于tkinter的组件介绍,可以自行百度,我这里就直接上代码了 

class Application(tk.Tk):

    def __init__(self):

            super().__init__()

            self.createUI()

    def createUI(self):

        self.ft = tf.Font(family='微软雅黑', size=18,weight=tf.BOLD)

        self.ft1 = tf.Font(family='微软雅黑', size=12)

        self.fm = tk.Frame(self)

        self.label = tk.Label(self.fm,text="计算结果:",font=self.ft)

        self.label.pack(side=tk.LEFT)

        self.fm_new1 = tk.Frame(self.fm)

        self.label0 = tk.Label(self.fm_new1,text="人民币:",font=self.ft1)

        self.label0.pack(side=tk.LEFT)

        self.entry0 = tk.Entry(self.fm_new1,font=self.ft1)

        self.entry0.pack(side=tk.LEFT)

        self.label11 = tk.Label(self.fm_new1,text="美元:",font=self.ft1)

        self.label11.pack(side=tk.LEFT)

        self.entry11 = tk.Entry(self.fm_new1,font=self.ft1)

        self.entry11.pack(side=tk.LEFT)

        self.fm_new1.pack(side=tk.TOP,padx=5, pady=10)

        self.fm_new2 = tk.Frame(self.fm)

        self.label12 = tk.Label(self.fm_new2,text="新加坡币:",font=self.ft1)

        self.label12.pack(side=tk.LEFT)

        self.entry12 = tk.Entry(self.fm_new2,font=self.ft1)

        self.entry12.pack(side=tk.LEFT)

        self.label13 = tk.Label(self.fm_new2,text="日元:",font=self.ft1)

        self.label13.pack(side=tk.LEFT)

        self.entry13 = tk.Entry(self.fm_new2,font=self.ft1)

        self.entry13.pack(side=tk.LEFT)

        self.fm_new2.pack(side=tk.TOP,padx=5, pady=10)

        self.fm.pack(side=tk.TOP,padx=5, pady=10)

        self.fm1 = tk.Frame(self)

        self.label1 = tk.Label(self.fm1,text="金 重:",font=self.ft1)

        self.label1.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry1 = tk.Entry(self.fm1,font=self.ft1)

        self.entry1.pack(side=tk.LEFT,padx=5, pady=10)

        self.label10 = tk.Label(self.fm1,text="浮动比率:",font=self.ft1)

        self.label10.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry10 = tk.Entry(self.fm1,font=self.ft1)

        self.entry10.pack(side=tk.LEFT,anchor=tk.W,padx=5, pady=10)

        self.fm1.pack(side=tk.TOP,padx=5, pady=5)

        self.fm2 = tk.Frame(self)

        self.label2 = tk.Label(self.fm2,text="金 价:",font=self.ft1)

        self.label2.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry2 = tk.Entry(self.fm2,font=self.ft1)

        self.entry2.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe3 = tk.Label(self.fm2,text="14K/18K:",font=self.ft1)

        self.labe3.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry3 = tk.Entry(self.fm2,font=self.ft1)

        self.entry3.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm2.pack(side=tk.TOP,padx=5, pady=5)

        self.fm3 = tk.Frame(self)

        self.label4 = tk.Label(self.fm3,text="主石重:",font=self.ft1)

        self.label4.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry4 = tk.Entry(self.fm3,font=self.ft1)

        self.entry4.pack(side=tk.LEFT,padx=5, pady=10)

        self.label5 = tk.Label(self.fm3,text="价  格:",font=self.ft1)

        self.label5.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry5 = tk.Entry(self.fm3,font=self.ft1)

        self.entry5.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm3.pack(side=tk.TOP,padx=5, pady=5)

        self.fm4 = tk.Frame(self)

        self.label6 = tk.Label(self.fm4,text="副石重:",font=self.ft1)

        self.label6.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry6 = tk.Entry(self.fm4,font=self.ft1)

        self.entry6.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe7 = tk.Label(self.fm4,text="价  格:",font=self.ft1)

        self.labe7.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry7 = tk.Entry(self.fm4,font=self.ft1)

        self.entry7.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm4.pack(side=tk.TOP,padx=5, pady=5)

        self.fm5 = tk.Frame(self)

        self.label8 = tk.Label(self.fm5,text="工费:",font=self.ft1)

        self.label8.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry8 = tk.Entry(self.fm5,font=self.ft1)

        self.entry8.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe9 = tk.Label(self.fm5,text="设计费:",font=self.ft1)

        self.labe9.pack(side=tk.LEFT,padx=5, pady=10)

        self.entry9 = tk.Entry(self.fm5,font=self.ft1)

        self.entry9.pack(side=tk.LEFT,padx=10, pady=10)

        self.fm5.pack(side=tk.TOP,padx=5, pady=5)

        self.fm6 = tk.Frame(self)

        self.selectButton = tk.Button(self.fm6, text="重置", command=self.selectFile,font=self.ft1)

        self.selectButton.pack(side=tk.LEFT,padx=10, pady=10)

        self.startButton = tk.Button(self.fm6, text="计算", command=lambda :self.thread_it(self.startAction),font=self.ft1)

        self.startButton.pack(side=tk.LEFT,padx=10, pady=10)

        self.fm6.pack(side=tk.TOP,padx=5, pady=5)

        self.title("我的计算器")

        #窗口大小

        width ,height= 600, 500

        #窗口居中显示

        self.geometry('%dx%d+%d+%d' % (width,height,(self.winfo_screenwidth() - width ) / 2, (self.winfo_screenheight() - height) / 2))

        #窗口最大值

        self.maxsize(600, 500)

        #窗口最小值

        self.minsize(300,200)

        self.entry0.insert('end',0)

        self.entry1.insert('end',0)

        self.entry2.insert('end',0)

        self.entry3.insert('end',0)

        self.entry4.insert('end',0)

        self.entry5.insert('end',0)

        self.entry6.insert('end',0)

        self.entry7.insert('end',0)

        self.entry8.insert('end',150)

        self.entry9.insert('end',50)

        self.entry10.insert('end',1.25)

        self.entry11.insert('end',0)

        self.entry12.insert('end',0)

        self.entry13.insert('end',0) 

说实话这段代码写的很随意,变量命名很随意,因为很多都是重复的东西,这里大致讲一下,首先是创建定义一个类继承自tkinter,这就相当于整个对象就是一个窗体了,之后就在这个窗体中进行布局,这里我们采用的是pack布局,说白了就是浮动布局,就是按照一行或者一列依次排列组件,这里就是利用Frame组件生成了几行的布局,然后在每个Frame里排列我们的标签和输入框,其中包含的一些细节就是组件的字体,组件之间的间距之类,完成了布局这一步之后,我们需要给按钮绑定事件,就是点击按钮触发什么操作,这里我们有两个按钮。 

其中重置按钮是为了清除输入的错误数据,绑定的事件就用command=self.selectFile这行代码来指定,这样就可以绑定到selectFile这个函数上,这个函数的代码如下所示 

    def selectFile(self):

        self.entry1.delete(0, "end")

        self.entry4.delete(0, "end")

        self.entry6.delete(0, "end")

        self.entry1.insert('end',0)

        self.entry4.insert('end',0)

        self.entry6.insert('end',0)

然后计算按钮是为了执行计算操作,这里我们采用了线程的方式进行绑定,也就是异步执行,不会卡住,避免因计算量过大导致程序假死的现象,绑定的方式是command=lambda :self.thread_it(self.startAction) 

绑定的函数如下所示 

    def startAction(self):

        A = self.entry1.get()

        print(A)

        B = self.entry2.get()

        print(B)

        C = self.entry3.get()

        print(C)

        D = self.entry4.get()

        print(D)

        E = self.entry5.get()

        print(E)

        F = self.entry6.get()

        print(F)

        G = self.entry7.get()

        print(G)

        H = self.entry8.get()

        print(H)

        I = self.entry9.get()

        print(I)

        J = self.entry10.get()

        print(J)

        result = ((float(A)*float(B)*float(C))+(float(D)*float(E))+(float(F)*float(G))+(float(H)+float(I)))*float(J)

        USDCNY,SGDCNY,JPYCNY = self.getRate()

        USDCNY_result = result/USDCNY

        SGDCNY_result = result/SGDCNY

        JPYCNY_result = USDCNY_result*JPYCNY

        self.entry0.delete(0, "end")

        self.entry0.insert('end',str(round(result, 2)))

        self.entry11.delete(0, "end")

        self.entry11.insert('end',str(round(USDCNY_result, 2)))

        self.entry12.delete(0, "end")

        self.entry12.insert('end',str(round(SGDCNY_result, 2)))

        self.entry13.delete(0, "end")

        self.entry13.insert('end',str(round(JPYCNY_result, 2)))

    @staticmethod

    def thread_it(func, *args):

        t = threading.Thread(target=func, args=args) 

        t.setDaemon(True)   

        t.start()  

至此基本完成了,不过完成的软件是这样的,如下所示 

初始版本 

可以看到比较明显的差异在计算结果那块,因为后面和客户沟通了,他需要其他币种的计算结果,所以后面就增加了几种结果,这里就用到了爬虫技术去采集实时的汇率,这里直接奉上了代码,直接解析的接口数据,所以很简单 

    def getRate(self):

        url = "http://webforex.hermes.hexun.com/forex/quotelist?code=FOREXUSDCNY,FOREXSGDCNY,FOREXUSDJPY&column=Code,Price"

        req = urllib.request.Request(url)

        f = urllib.request.urlopen(req)

        html = f.read().decode("utf-8")

        print(html)

        s = re.findall("{.*}",str(html))[0]

        sjson = json.loads(s)

        USDCNY = sjson["Data"][0][0][1]/10000

        print(USDCNY)

        SGDCNY = sjson["Data"][0][1][1]/10000

        print(SGDCNY)

        JPYCNY = sjson["Data"][0][2][1]/10000

        print(JPYCNY)

        return USDCNY,SGDCNY,JPYCNY 

至此,Python代码基本完成了,这里奉上完整的代码 

import tkinter as tk

from tkinter import filedialog

from tkinter import messagebox

import threading

import tkinter.font as tf

import re

import json

import urllib.request

class Application(tk.Tk):

    def __init__(self):

            super().__init__()

            self.createUI()

    def createUI(self):

        self.ft = tf.Font(family='微软雅黑', size=18,weight=tf.BOLD)

        self.ft1 = tf.Font(family='微软雅黑', size=12)

        self.fm = tk.Frame(self)

        self.label = tk.Label(self.fm,text="计算结果:",font=self.ft)

        self.label.pack(side=tk.LEFT)

        self.fm_new1 = tk.Frame(self.fm)

        self.label0 = tk.Label(self.fm_new1,text="人民币:",font=self.ft1)

        self.label0.pack(side=tk.LEFT)

        self.entry0 = tk.Entry(self.fm_new1,font=self.ft1)

        self.entry0.pack(side=tk.LEFT)

        self.label11 = tk.Label(self.fm_new1,text="美元:",font=self.ft1)

        self.label11.pack(side=tk.LEFT)

        self.entry11 = tk.Entry(self.fm_new1,font=self.ft1)

        self.entry11.pack(side=tk.LEFT)

        self.fm_new1.pack(side=tk.TOP,padx=5, pady=10)

        self.fm_new2 = tk.Frame(self.fm)

        self.label12 = tk.Label(self.fm_new2,text="新加坡币:",font=self.ft1)

        self.label12.pack(side=tk.LEFT)

        self.entry12 = tk.Entry(self.fm_new2,font=self.ft1)

        self.entry12.pack(side=tk.LEFT)

        self.label13 = tk.Label(self.fm_new2,text="日元:",font=self.ft1)

        self.label13.pack(side=tk.LEFT)

        self.entry13 = tk.Entry(self.fm_new2,font=self.ft1)

        self.entry13.pack(side=tk.LEFT)

        self.fm_new2.pack(side=tk.TOP,padx=5, pady=10)

        self.fm.pack(side=tk.TOP,padx=5, pady=10)

        self.fm1 = tk.Frame(self)

        self.label1 = tk.Label(self.fm1,text="金 重:",font=self.ft1)

        self.label1.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry1 = tk.Entry(self.fm1,font=self.ft1)

        self.entry1.pack(side=tk.LEFT,padx=5, pady=10)

        self.label10 = tk.Label(self.fm1,text="浮动比率:",font=self.ft1)

        self.label10.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry10 = tk.Entry(self.fm1,font=self.ft1)

        self.entry10.pack(side=tk.LEFT,anchor=tk.W,padx=5, pady=10)

        self.fm1.pack(side=tk.TOP,padx=5, pady=5)

        self.fm2 = tk.Frame(self)

        self.label2 = tk.Label(self.fm2,text="金 价:",font=self.ft1)

        self.label2.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry2 = tk.Entry(self.fm2,font=self.ft1)

        self.entry2.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe3 = tk.Label(self.fm2,text="14K/18K:",font=self.ft1)

        self.labe3.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry3 = tk.Entry(self.fm2,font=self.ft1)

        self.entry3.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm2.pack(side=tk.TOP,padx=5, pady=5)

        self.fm3 = tk.Frame(self)

        self.label4 = tk.Label(self.fm3,text="主石重:",font=self.ft1)

        self.label4.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry4 = tk.Entry(self.fm3,font=self.ft1)

        self.entry4.pack(side=tk.LEFT,padx=5, pady=10)

        self.label5 = tk.Label(self.fm3,text="价  格:",font=self.ft1)

        self.label5.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry5 = tk.Entry(self.fm3,font=self.ft1)

        self.entry5.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm3.pack(side=tk.TOP,padx=5, pady=5)

        self.fm4 = tk.Frame(self)

        self.label6 = tk.Label(self.fm4,text="副石重:",font=self.ft1)

        self.label6.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry6 = tk.Entry(self.fm4,font=self.ft1)

        self.entry6.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe7 = tk.Label(self.fm4,text="价  格:",font=self.ft1)

        self.labe7.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry7 = tk.Entry(self.fm4,font=self.ft1)

        self.entry7.pack(side=tk.LEFT,padx=5, pady=10)

        self.fm4.pack(side=tk.TOP,padx=5, pady=5)

        self.fm5 = tk.Frame(self)

        self.label8 = tk.Label(self.fm5,text="工费:",font=self.ft1)

        self.label8.pack(side=tk.LEFT,padx=10, pady=10)

        self.entry8 = tk.Entry(self.fm5,font=self.ft1)

        self.entry8.pack(side=tk.LEFT,padx=5, pady=10)

        self.labe9 = tk.Label(self.fm5,text="设计费:",font=self.ft1)

        self.labe9.pack(side=tk.LEFT,padx=5, pady=10)

        self.entry9 = tk.Entry(self.fm5,font=self.ft1)

        self.entry9.pack(side=tk.LEFT,padx=10, pady=10)

        self.fm5.pack(side=tk.TOP,padx=5, pady=5)

        self.fm6 = tk.Frame(self)

        self.selectButton = tk.Button(self.fm6, text="重置", command=self.selectFile,font=self.ft1)

        self.selectButton.pack(side=tk.LEFT,padx=10, pady=10)

        self.startButton = tk.Button(self.fm6, text="计算", command=lambda :self.thread_it(self.startAction),font=self.ft1)

        self.startButton.pack(side=tk.LEFT,padx=10, pady=10)

        self.fm6.pack(side=tk.TOP,padx=5, pady=5)

        self.title("我的计算器")

        #窗口大小

        width ,height= 600, 500

        #窗口居中显示

        self.geometry('%dx%d+%d+%d' % (width,height,(self.winfo_screenwidth() - width ) / 2, (self.winfo_screenheight() - height) / 2))

        #窗口最大值

        self.maxsize(600, 500)

        #窗口最小值

        self.minsize(300,200)

        self.entry0.insert('end',0)

        self.entry1.insert('end',0)

        self.entry2.insert('end',0)

        self.entry3.insert('end',0)

        self.entry4.insert('end',0)

        self.entry5.insert('end',0)

        self.entry6.insert('end',0)

        self.entry7.insert('end',0)

        self.entry8.insert('end',150)

        self.entry9.insert('end',50)

        self.entry10.insert('end',1.25)

        self.entry11.insert('end',0)

        self.entry12.insert('end',0)

        self.entry13.insert('end',0)

    def selectFile(self):

        self.entry1.delete(0, "end")

        self.entry4.delete(0, "end")

        self.entry6.delete(0, "end")

        self.entry1.insert('end',0)

        self.entry4.insert('end',0)

        self.entry6.insert('end',0)

    def startAction(self):

        A = self.entry1.get()

        print(A)

        B = self.entry2.get()

        print(B)

        C = self.entry3.get()

        print(C)

        D = self.entry4.get()

        print(D)

        E = self.entry5.get()

        print(E)

        F = self.entry6.get()

        print(F)

        G = self.entry7.get()

        print(G)

        H = self.entry8.get()

        print(H)

        I = self.entry9.get()

        print(I)

        J = self.entry10.get()

        print(J)

        result = ((float(A)*float(B)*float(C))+(float(D)*float(E))+(float(F)*float(G))+(float(H)+float(I)))*float(J)

        USDCNY,SGDCNY,JPYCNY = self.getRate()

        USDCNY_result = result/USDCNY

        SGDCNY_result = result/SGDCNY

        JPYCNY_result = USDCNY_result*JPYCNY

        self.entry0.delete(0, "end")

        self.entry0.insert('end',str(round(result, 2)))

        self.entry11.delete(0, "end")

        self.entry11.insert('end',str(round(USDCNY_result, 2)))

        self.entry12.delete(0, "end")

        self.entry12.insert('end',str(round(SGDCNY_result, 2)))

        self.entry13.delete(0, "end")

        self.entry13.insert('end',str(round(JPYCNY_result, 2)))

    @staticmethod

    def thread_it(func, *args):

        t = threading.Thread(target=func, args=args) 

        t.setDaemon(True)   

        t.start()  

    def getRate(self):

        url = "http://webforex.hermes.hexun.com/forex/quotelist?code=FOREXUSDCNY,FOREXSGDCNY,FOREXUSDJPY&column=Code,Price"

        req = urllib.request.Request(url)

        f = urllib.request.urlopen(req)

        html = f.read().decode("utf-8")

        print(html)

        s = re.findall("{.*}",str(html))[0]

        sjson = json.loads(s)

        USDCNY = sjson["Data"][0][0][1]/10000

        print(USDCNY)

        SGDCNY = sjson["Data"][0][1][1]/10000

        print(SGDCNY)

        JPYCNY = sjson["Data"][0][2][1]/10000

        print(JPYCNY)

        return USDCNY,SGDCNY,JPYCNY

app = Application()

app.mainloop()

# root.mainloop() 

但是到这一步,还差一点点,因为我们的目的是生成一个exe软件,可以给没有安装Python环境的人使用,所以我们要用到Python的软件打包工具,这里我们使用的是pyinstaller,使用起来也很方便,直接用命令行进入python文件所在的文件夹,执行pyinstaller -F app.py --noconsole 即可,这里的app.py指代的是你们需要打包的python文件名,--noconsole是指打包成的exe文件运行时不显示控制台黑窗口。执行完成即可在同级目录下的dist文件中找到你们打包好的exe文件,至此,本文结束。 

最终样式 

本文首发于https://www.bizhibihui.com/

原文链接:https://blog.csdn.net/qq_23830377/article/details/108518299?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160585599619724836709013%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160585599619724836709013&biz_id=0&utm_medium=distribute.pc_search_result.no

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python小练习----秒表

    from tkinter import * import time class StopWatch(Frame):     '''实现一个秒表部件'''    ...

    用户7886150
  • python实现的摩斯电码解码\编码器

    代码地址如下:http://www.demodashi.com/demo/14743.html

    用户7886150
  • Python 面向对象编程

    二类:由抽象信息或者动作组成的集合,代表一类事物,抽象名词实例(对象):具象的,是一类事物中某一个具体的事物

    用户7886150
  • PyQt5 对话框 数据验证

    本篇介绍PyQt5对话框的数据合法性的验证。有两种验证方式:预防式验证(preventative)和 提交后验证 (post-mortem)。预防式验证适合于单...

    用户6021899
  • MicroPython开发实例之自制小型家庭气象站

    众所周知,iPhone6/6Plus内置气压传感器,不过大家对于气压传感器还是很陌生。跟字面的意思一样,气压传感器就是用来测量气压的,但测量气压对于普通的手机用...

    周俊辉
  • 我的tkinter学习笔记4

    用户6367961
  • redis流计算

    使用了tornado的异步和streamz的流处理两个库,需要redis 5.0以上版本

    spark
  • 箱线图(BoxPlot) App

    由于公司的Execl版本(v2010)偏低,没有画箱线图的功能,故我用python写了一小段程序,可以用来画箱线图。绘图库使用的还是matplotlib。

    用户6021899
  • ​Python人工智能在贪吃蛇游戏中的运用与探索(下)

    之前,我们简单的分析介绍了实现贪吃蛇的基本原理和工具,本篇我们将进一步用代码分析其具体的形成过程。

    用户1621951
  • Python | Queue 队列源码分析

    queue 模块提供适用于多线程编程的先进先出(FIFO)数据结构。因为它是线程安全的,所以多个线程很轻松地使用同一个实例。

    咸鱼学Python

扫码关注云+社区

领取腾讯云代金券