PyQt5学习教程18:70行的货币转换程序

在上一篇教程中,我们已经分析了“货币转换程序”的具体编程思路,本教程我们来详细的探讨一下,程序的具体细节,先看源程序。


源程序:

import sys
from PyQt5.QtWidgets import QWidget, \
                              QPushButton, \
                              QToolTip, \
                              QMessageBox, \
                              QApplication, \
                              QDesktopWidget, \
                              QMainWindow, \
                              QAction, \
                              qApp, \
                              QVBoxLayout, \
                              QHBoxLayout, \
                              QTextBrowser, \
                              QLineEdit, \
                              QLabel, \
                              QComboBox, \
                              QGridLayout
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, \
                          QIcon
import urllib.request


# QMainWindow是QWidget的派生类
class CMainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        # ToolTip设置
        QToolTip.setFont(QFont('华文楷体', 10))

        # statusBar设置
        self.statusBar().showMessage('准备就绪')

        # 退出Action设置
        exitAction = QAction(QIcon('1.png'), '&退出', self)
        exitAction.setShortcut('ctrl+Q')
        exitAction.setStatusTip('退出应用程序')
        exitAction.triggered.connect(qApp.quit)     # qApp就相当于QCoreApplication.instance()

        # menuBar设置
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&文件')
        fileMenu.addAction(exitAction)

        # toolBar设置
        self.toolbar = self.addToolBar('文件')
        self.toolbar.addAction(exitAction)

        # 确认PushButton设置
        btnExchange = QPushButton("转换")
        btnExchange.setToolTip("将人民币转换为对应货币!")
        btnExchange.setStatusTip("将人民币转换为对应货币!")
        btnExchange.clicked.connect(self.funExchange)
        btnExchange.resize(btnExchange.sizeHint())

        # 退出PushButton设置
        btnQuit = QPushButton('退出')
        btnQuit.setToolTip("点击此按钮将退出应用程序!")
        btnQuit.setStatusTip("点击此按钮将退出应用程序!")
        btnQuit.clicked.connect(qApp.quit)
        btnQuit.resize(btnQuit.sizeHint())

        # PushButton布局
        hBox1 = QHBoxLayout()
        hBox1.addStretch(1)
        hBox1.addWidget(btnExchange)
        hBox1.addWidget(btnQuit)

        # 标签
        self.labDate = QLabel("日期:")                             # 汇率日期
        self.labCurrency = QLabel("货币:")                        # 欲转换的货币
        self.labExchange = QLabel("加元汇率:")                    # 加元对该货币的汇率
        self.labCanadaToChina = QLabel("加元对人民币汇率:")       # 加元对人民比的汇率
        self.labChina = QLabel("人民币对该货币汇率:")             # 人民币对该货币的汇率
        self.labChinaQuality = QLabel("人民币:")                  # 转换金额
        self.labCurrencyQuality = QLabel("转换货币:")             # 转换后的货币金额
        self.labData = QLabel("原始数据:")                        # 计算的原数数据和中间过程数据输出
        # 复合框和单行文本框
        self.lineDate = QLineEdit("")
        self.lineDate.setReadOnly(True)
        self.comCurrency = QComboBox()
        self.comCurrency.currentIndexChanged.connect(self.funReadExchange)
        self.lineExchange = QLineEdit("")
        self.lineExchange.setReadOnly(True)
        self.lineCanadaToChina = QLineEdit("")
        self.lineCanadaToChina.setReadOnly(True)
        self.lineChina = QLineEdit("")
        self.lineChina.setReadOnly(True)
        self.lineChinaQuality = QLineEdit("1000.00")
        self.lineCurrencyQuality = QLineEdit("0.00")
        self.lineCurrencyQuality.setReadOnly(True)
        # 多行文本框
        self.textData = QTextBrowser()

        # 定义字典和列表
        self.dicCurrency = {}       # 存储货币信息
        self.dicDescription = {}    # 存储货币的描述信息
        self.dicExchange = {}       # 存储汇率信息
        self.listRow = []           # 指定每种货币所在的列

        # 读取数据
        try:
            self.data = urllib.request.urlopen("http://www.bankofcanada.ca/valet/observations/" 
                                          "FXCADAUD,FXCADBRL,FXCADCNY,FXCADEUR,FXCADHKD,FXCADINR,FXCADIDR,"
                                          "FXCADJPY,FXCADMYR,FXCADMXN,FXCADNZD,FXCADNOK,FXCADPEN,FXCADRUB,"
                                          "FXCADSAR,FXCADSGD,FXCADZAR,FXCADKRW,FXCADSEK,FXCADCHF,FXCADTWD,"
                                          "FXCADTHB,FXCADTRY,FXCADGBP,FXCADUSD,FXCADVND/csv").read()
            for line in self.data.decode("utf-8", "replace").split('\n'):    # 调用decode方法直接将数据转换为utf-8,否则应使用str将其转换为字符串
                line = line.rstrip()    # 除去字符串尾指定字符,默认为空格
                # 取得货币缩写代码
                if line.startswith("FXC"):
                    temp = line.split(",")
                    self.dicCurrency.setdefault(temp[0], temp[1].strip("\"")[4:7])
                    description = temp[2].strip("\"")
                    description = description.split(" ")
                    if description[5] == 'daily':
                        description = "加元对 " + description[3] + " " + description[4] + " 汇率:"
                    else:
                        description = "加元对 " + description[3] + " " + description[4] + " " + description[5] + " 汇率:"
                    self.dicDescription.setdefault(temp[0], description)
                # 取得货币所在的列号
                elif line.startswith("date"):
                    self.listRow = line.split(",")
                # 当读出错误时,退出
                elif line.startswith("ERRORS"):
                    break
                else:
                    temp = line.split(",")
                    if temp[0][4:5] == '-' and temp[1] != '':
                        self.dicExchange = {}
                        for index in range(len(temp)):
                            self.dicExchange.setdefault(self.listRow[index], temp[index])
            # 将货币加入复合框
            for key in self.dicCurrency:
                self.comCurrency.addItem(self.dicCurrency[key])
            # 输出汇率信息
            for key in self.dicExchange:
                self.textData.append(self.dicExchange[key])
            # 输出日期
            self.lineDate.setText(self.dicExchange['date'])
            # 输出加拿大元对人民币汇率
            self.lineCanadaToChina.setText(self.dicExchange['FXCADCNY'])
        except Exception as e:
            self.textData.setText("加载数据失败,请检查网络连接,错误:\n{}".format(e))

        # GridLayout布局
        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(self.labDate, 1, 0)
        grid.addWidget(self.lineDate, 1, 1)
        grid.addWidget( self.labCurrency, 2, 0)
        grid.addWidget(self.comCurrency, 2, 1)
        grid.addWidget(self.labExchange, 3, 0)
        grid.addWidget(self.lineExchange, 3, 1)
        grid.addWidget(self.labCanadaToChina, 4, 0)
        grid.addWidget(self.lineCanadaToChina, 4, 1)
        grid.addWidget(self.labChina, 5, 0)
        grid.addWidget(self.lineChina, 5, 1)
        grid.addWidget(self.labChinaQuality, 6, 0)
        grid.addWidget(self.lineChinaQuality, 6, 1)
        grid.addWidget(self.labCurrencyQuality, 7, 0)
        grid.addWidget(self.lineCurrencyQuality, 7, 1)
        grid.addWidget(self.labData, 8, 0)
        grid.addWidget(self.textData, 8, 1, 15, 1)

        # 布局
        vBox = QVBoxLayout()
        vBox.addLayout(grid)
        vBox.addLayout(hBox1)
        widget = QWidget()
        self.setCentralWidget(widget)  # 建立的widget在窗体的中间位置
        widget.setLayout(vBox)

        # Window设置
        self.resize(500, 300)
        self.center()
        self.setFont(QFont('华文楷体', 10))
        self.setWindowTitle('PyQt5应用教程(snmplink编著)')
        self.setWindowIcon(QIcon('10.png'))
        self.show()

    def center(self):
        # 得到主窗体的框架信息
        qr = self.frameGeometry()
        # 得到桌面的中心
        cp = QDesktopWidget().availableGeometry().center()
        # 框架的中心与桌面中心对齐
        qr.moveCenter(cp)
        # 自身窗体的左上角与框架的左上角对齐
        self.move(qr.topLeft())

    def funExchange(self):
        try:
            self.lineCurrencyQuality.setText("{0:.2f}".format(float(self.lineChinaQuality.text()) * float(self.lineChina.text())))
        except Exception as e:
            self.textData.setText("加载数据失败,请检查网络连接,错误:\n{}".format(e))

    def funReadExchange(self):
        # 显示描述信息
        try:
            for key in self.dicCurrency:
                if self.dicCurrency[key] == self.comCurrency.currentText():
                    self.labExchange.setText(self.dicDescription[key])
                    self.lineExchange.setText(self.dicExchange[key])
                    self.lineChina.setText("{0:.2f}".format(float(self.dicExchange[key]) / float(self.dicExchange['FXCADCNY'])))
                    break
            self.funExchange()
        except Exception as e:
            self.textData.setText("加载数据失败,请检查网络连接,错误:\n{}".format(e))

    def keyPressEvent(self, e):
        if e.key() == Qt.Key_Escape:
            self.close()

    def closeEvent(self, QCloseEvent):
        reply = QMessageBox.question(self,
                                     'PyQt5应用教程(snmplink编著)',
                                     "是否要退出应用程序?",
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            QCloseEvent.accept()
        else:
            QCloseEvent.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = CMainWindow()
    sys.exit(app.exec_())

1、第21行:输入urlib.request模块,我们使用该模块可以通过http协议,访问网上信息。

2、第52-56行:设置转换PushButton的相关内容。

3、第72-79行:设置标签信息,具体的用途可以参考一下注解信息。

4、第81-95行:设置复合框、单行文本框和多行文本框的内容,其排列顺序与标签信息相同,大家对照着看一下。

5、第98行:定义字典dicCurrency,用于存储货币的缩写信息。

6、第99行:定义字典dicDescription,用于存储货币的描述信息。

7、第100行:定义字典dicExchange,用于存储货币的汇率信息(这里是加元对该货币的汇率)。

8、第101行:定义列表listRow,用于存储查找CSV第2部分内容的列信息。

9、第105-109行:从网上读取CSV文件。

10、第110行:按行遍历读取到的数据,这里首先将数据转换为utf-8,然后通过'\n'进行行的分割。

11、第111行:除去字符串尾部的空格。

12、第113行:判断行的首字符是否为“FXC”,从而判断是否为CSV的第1部分内容。

13、第114行:将行信息按照“,”进行分割,存入列表。temp[0]从存储的是索引,temp[1]中存储的是货币缩写,temp[2]中存储的是货币描述。

14、第115行:按照索引信息将内容加入dicCurrency,至于[4:7]的理解,大家要看一下原始文件。

15、第116-122行:处理描述信息,将其加入字典dicDescription。

16、第124-125行:如果首字符是"date",则是CSV文件中,第2部分的第1行,我们将其信息存入listRow列表。

17、第130-134行:对汇率信息进行处理,如果当前行有内容,则覆盖上1行的内容,将数据加入dicExchange字典。

18、第136-137行:读取到的货币缩写字典dicCurrency内容,加入复合文本框。

19、第139-140行:在textData中输出汇率信息,这仅是为了调试,你可以输入其它调试内容。

20、第142行:输出最新的汇率日期。

21、第144行:输出加元对人民币汇率。

22、第149-166行:通过GridLayout进行布局。

23、第195-198行:进行货币计算。

23、第200-221行:处理复合框索引变化,如果变换则更改其它行的相应信息,并调用funExchange进行货币计算。

其它的信息,如果有看不明白的,翻看先前的教程即可。


原创性文章,转载请注明出处 http://user.qzone.qq.com/2756567163     
CSDN:http://blog.csdn.net/qingwufeiyang12346



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

snmplink

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值