• 4609阅读
  • 5回复

解决第4章例子“70行货币转换程序”对PyQt5+Python3兼容性的问题 [复制链接]

上一主题 下一主题
离线wps2000
 

只看楼主 倒序阅读 楼主  发表于: 2016-10-12
先上最初的源码:
===================================================================
import sys
import urllib2
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        date = self.getdata()
        rates = sorted(self.rates.keys())

        dateLabel = QLabel(date)
        self.fromComboBox = QComboBox()
        self.fromComboBox.addItems(rates)
        self.fromSpinBox = QDoubleSpinBox()
        self.fromSpinBox.setRange(0.01, 10000000.00)
        self.fromSpinBox.setValue(1.00)
        self.toComboBox = QComboBox()
        self.toComboBox.addItems(rates)
        self.toLabel = QLabel("1.00")
        grid = QGridLayout()
        grid.addWidget(dateLabel, 0, 0)
        grid.addWidget(self.fromComboBox, 1, 0)
        grid.addWidget(self.fromSpinBox, 1, 1)
        grid.addWidget(self.toComboBox, 2, 0)
        grid.addWidget(self.toLabel, 2, 1)
        self.setLayout(grid)
        self.connect(self.fromComboBox,
                SIGNAL("currentIndexChanged(int)"), self.updateUi)
        self.connect(self.toComboBox,
                SIGNAL("currentIndexChanged(int)"), self.updateUi)
        self.connect(self.fromSpinBox,
                SIGNAL("valueChanged(double)"), self.updateUi)
        self.setWindowTitle("Currency")


    def updateUi(self):
        to = unicode(self.toComboBox.currentText())
        from_ = unicode(self.fromComboBox.currentText())
        amount = (self.rates[from_] / self.rates[to]) * \
                 self.fromSpinBox.value()
        self.toLabel.setText("%0.2f" % amount)


    def getdata(self): # Idea taken from the Python Cookbook
        self.rates = {}
        try:
            date = "Unknown"
            fh = urllib2.urlopen("http://www.bankofcanada.ca"
                                 "/en/markets/csv/exchange_eng.csv")
            for line in fh:
                line = line.rstrip()
                if not line or line.startswith(("#", "Closing ")):
                    continue
                fields = line.split(",")
                if line.startswith("Date "):
                    date = fields[-1]
                else:
                    try:
                        value = float(fields[-1])
                        self.rates[unicode(fields[0])] = value
                    except ValueError:
                        pass
            return "Exchange Rates Date: " + date
        except Exception, e:
            return "Failed to download:\n%s" % e


app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
===============================================================
在最初的源码中,界面用是PyQt4,抓取数据用的是urllib2。在PyQT5中,connect方法已经改变了。在Python3.x中,urllib2已变成了urllib,使用方法也大不相同。首先,把原来的模块引入修改成:

import sys
import re #引入了正则表达式模块
import urllib.request #把urllib2改成urllib
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import * #QApplication 已经定位到PyQt5.QtWidgets这个模块

引入正则表达式模块,是因为要对原来的代码中的getdata方法进行修改。另外,在这几行中:
self.connect(self.fromComboBox,
                SIGNAL("currentIndexChanged(int)"), self.updateUi)
        self.connect(self.toComboBox,
                SIGNAL("currentIndexChanged(int)"), self.updateUi)
        self.connect(self.fromSpinBox,
                SIGNAL("valueChanged(double)"), self.updateUi)

我前面说了,connect方法已经变了。要变成:

self.fromComboBox.currentIndexChanged.connect(self.updateUi)
self.toComboBox.currentIndexChanged.connect(self.updateUi)
self.fromSpinBox.valueChanged.connect(self.updateUi)

另外,还要把带有unicode的函数去掉,因为python3.x默认就是unicode编码。最后,修改后的完整代码就是这样:

=======================================================================================


import sys
import re #引入了正则表达式模块
import urllib.request#把urllib2改成urllib
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import * #QApplication 已经定位到PyQt5.QtWidgets这个模块


class Form(QDialog):

    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        date = self.getdata()
        rates = sorted(self.rates.keys())

        dateLabel = QLabel(date)
        self.fromComboBox = QComboBox()
        self.fromComboBox.addItems(rates)
        self.fromSpinBox = QDoubleSpinBox()
        self.fromSpinBox.setRange(0.01, 10000000.00)
        self.fromSpinBox.setValue(1.00)
        self.toComboBox = QComboBox()
        self.toComboBox.addItems(rates)
        self.toLabel = QLabel("1.00")
        grid = QGridLayout()
        grid.addWidget(dateLabel, 0, 0)
        grid.addWidget(self.fromComboBox, 1, 0)
        grid.addWidget(self.fromSpinBox, 1, 1)
        grid.addWidget(self.toComboBox, 2, 0)
        grid.addWidget(self.toLabel, 2, 1)
        self.setLayout(grid)
        self.fromComboBox.currentIndexChanged.connect(self.updateUi)
        self.toComboBox.currentIndexChanged.connect(self.updateUi)
        self.fromSpinBox.valueChanged.connect(self.updateUi)
        self.setWindowTitle("Currency")


    def updateUi(self):
        to = self.toComboBox.currentText()#把unicode去掉
        from_ = self.fromComboBox.currentText()#把unicode去掉
        amount = (self.rates[from_] / self.rates[to]) * \
                 self.fromSpinBox.value()
        self.toLabel.setText("%0.2f" % amount)

    

    def getdata(self):
        self.rates = {}
        try:
            date = "Unknown"
            fh = urllib.request.urlopen("http://www.bankofcanada.ca/en/markets/csv/exchange_eng.csv")
            csv_data = str(fh.read())
            pattern = re.compile('Date[\s\S]*')#以"Date"关键词,匹配"Date"之后的数据
            csv_data = pattern.search(csv_data)
            csv_data = csv_data.group(0)
            csv_data = csv_data.split("\\n")#以换行符为标志生成数据列表

            for line in csv_data:
                if "Date" in line:#如果数据行包含“Date”项,就将最后的日期作为date的值
                    date = line.split(',')[-1]#以逗号进行分割,获得最后的日期
                else:
                    temp = line.split(',')#以逗号进行分割,获得每一行的数据,生成一个临时列表
                    if temp[0] is not "\'":
                        key = temp[0]#将临时列表的第1项作为汇率名
                        value = temp[-1]#将这个列表的最后一项作为汇率值
                        self.rates[key] = float(value)#生成汇率字典

            return "Exchange Rates Date: " + date
        
        
        except Exception as e: #在python3.x中,要将逗号改成as
            return "Failed to download:\n%s" % e


app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

==================================================================================

上述代码中,getdata方法改动最大,但也比较容易理解。关键是,能配合urllib对数据进行获取。
离线jxgzhelong

只看该作者 1楼 发表于: 2017-03-16

最近怎么不更新了呢
离线linote

只看该作者 2楼 发表于: 2017-04-20
离线miaotiian308

只看该作者 3楼 发表于: 2017-08-19
使用以上链接,为什么是“Failed to download:HTTP Error 404:Not Found"
离线wps2000

只看该作者 4楼 发表于: 2017-10-28
回 miaotiian308 的帖子
miaotiian308:使用以上链接,为什么是“Failed to download:HTTP Error 404:Not Found" (2017-08-19 15:55) 

那个数据没有了。在google上搜索新的吧。
离线kite99

只看该作者 5楼 发表于: 2018-07-24
    
快速回复
限100 字节
 
上一个 下一个