Python GUI 编程(七)
原文:
zh.annas-archive.org/md5/9d5f7126bd532a80dd6a9dce44175aaa译者:飞龙
第二十一章:实现动画
在本章中,您将学习如何对给定的图形图像应用运动,从而实现动画。动画在解释任何机器、过程或系统的实际工作中起着重要作用。在本章中,我们将涵盖以下主题:
-
显示 2D 图形图片
-
点击按钮使球移动
-
制作一个弹跳的球
-
使球根据指定的曲线进行动画
介绍
要在 Python 中查看和管理 2D 图形项,我们需要使用一个名为QGraphicsScene的类。为了显示QGraphicsScene的内容,我们需要另一个名为QGraphicsView的类的帮助。基本上,QGraphicsView提供了一个可滚动的视口,用于显示QGraphicsScene的内容。QGraphicsScene充当多个图形项的容器。它还提供了几种标准形状,如矩形和椭圆,包括文本项。还有一点:QGraphicsScene使用 OpenGL 来渲染图形。OpenGL 非常高效,可用于显示图像和执行多媒体处理任务。QGraphicsScene类提供了几种方法,可帮助添加或删除场景中的图形项。也就是说,您可以通过调用addItem函数向场景添加任何图形项。同样,要从图形场景中删除项目,可以调用removeItem函数。
实现动画
要在 Python 中应用动画,我们将使用QPropertyAnimation类。PyQt 中的QPropertyAnimation类帮助创建和执行动画。QPropertyAnimation类通过操纵 Qt 属性(如小部件的几何形状、位置等)来实现动画。以下是QPropertyAnimation的一些方法:
-
start(): 该方法开始动画 -
stop(): 该方法结束动画 -
setStartValue(): 该方法用于指定动画的起始值 -
setEndValue(): 该方法用于指定动画的结束值 -
setDuration(): 该方法用于设置动画的持续时间(毫秒) -
setKeyValueAt(): 该方法在给定值处创建关键帧 -
setLoopCount(): 该方法设置动画中所需的重复次数
显示 2D 图形图像
在本教程中,您将学习如何显示 2D 图形图像。我们假设您的计算机上有一个名为scene.jpg的图形图像,并将学习如何在表单上显示它。本教程的重点是了解如何使用 Graphics View 小部件来显示图像。
操作步骤…
显示图形的过程非常简单。您首先需要创建一个QGraphicsScene对象,该对象又利用QGraphicsView类来显示其内容。然后通过调用QGraphicsScene类的addItem方法向QGraphicsScene类添加图形项,包括图像。以下是在屏幕上显示 2D 图形图像的步骤:
-
基于无按钮对话框模板创建一个新应用程序。
-
将 Graphics View 小部件拖放到其中。
-
将应用程序保存为
demoGraphicsView.ui。表单将显示如下截图所示:
pyuic5命令实用程序将.ui(XML)文件转换为 Python 代码。生成的 Python 脚本demoGraphicsView.py可以在本书的源代码包中找到。
- 创建一个名为
callGraphicsView.pyw的 Python 脚本,导入代码demoGraphicsView.py,以调用用户界面设计,从磁盘加载图像,并通过 Graphics View 显示它。Python 脚本文件callGraphicsView.pyw将包括以下代码:
import sys
from PyQt5.QtWidgets import QDialog, QApplication, QGraphicsScene, QGraphicsPixmapItem
from PyQt5.QtGui import QPixmap
from demoGraphicsView import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.scene = QGraphicsScene(self)
pixmap= QtGui.QPixmap()
pixmap.load("scene.jpg")
item=QGraphicsPixmapItem(pixmap)
self.scene.addItem(item)
self.ui.graphicsView.setScene(self.scene)
if __name__=="__main__":
app = QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
工作原理…
在此应用程序中,您正在使用 Graphics View 来显示图像。您向 Graphics View 小部件添加了一个图形场景,并添加了QGraphicsPixmapItem。如果要将图像添加到图形场景中,需要以pixmap项目的形式提供。首先,您需要将图像表示为pixmap,然后在将其添加到图形场景之前将其显示为pixmap项目。您需要创建QPixmap的实例,并通过其load()方法指定要通过其显示的图像。然后,通过将pixmap传递给QGraphicsPixmapItem的构造函数,将pixmap项目标记为pixmapitem。然后,通过addItem将pixmapitem添加到场景中。如果pixmapitem比QGraphicsView大,则会自动启用滚动。
在上面的代码中,我使用了文件名为scene.jpg的图像。请将文件名替换为您的磁盘上可用的图像文件名,否则屏幕上将不显示任何内容。
使用了以下方法:
-
QGraphicsView.setScene:此方法(self,QGraphicsScenescene)将提供的场景分配给GraphicView实例以进行显示。如果场景已经在视图中显示,则此函数不执行任何操作。设置场景时,将生成QGraphicsScene.changed信号,并调整视图的滚动条以适应场景的大小。 -
addItem:此方法将指定的项目添加到场景中。如果项目已经在不同的场景中,则首先将其从旧场景中移除,然后添加到当前场景中。运行应用程序时,将通过GrahicsView小部件显示scene.jpg图像,如下面的屏幕截图所示:
点击按钮使球移动
在本教程中,您将了解如何在对象上应用基本动画。本教程将包括一个按钮和一个球,当按下按钮时,球将开始向地面动画。
操作步骤…
为了制作这个教程,我们将使用QPropertyAnimation类。QPropertyAnimation类的setStartValue()和setEndValue()方法将用于分别定义动画需要开始和结束的坐标。setDuration()方法将被调用以指定每次动画移动之间的延迟时间(以毫秒为单位)。以下是应用动画的逐步过程:
-
基于无按钮对话框模板创建一个新应用程序。
-
将一个 Label 小部件和一个 Push Button 小部件拖放到表单上。
-
将 Push Button 小部件的文本属性设置为
Move Down。我们假设您的计算机上有一个名为coloredball.jpg的球形图像。 -
选择其 pixmap 属性以将球图像分配给 Label 小部件。
-
在 pixmap 属性中,从两个选项中选择 Resource 和 Choose File,选择 Choose File 选项,浏览您的磁盘,并选择
coloredball.jpg文件。球的图像将出现在 Label 小部件的位置。 -
将 Push Button 小部件的 objectName 属性设置为
pushButtonPushDown,Label 小部件的 objectName 属性设置为labelPic。 -
使用名称
demoAnimation1.ui保存应用程序。应用程序将显示如下屏幕截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,这是一个需要转换为 Python 代码的 XML 文件。在应用pyuic5命令实用程序时,.ui文件将被转换为 Python 脚本。生成的 Python 脚本demoAnimation1.py可以在本书的源代码包中看到。
-
将
demoAnimation1.py脚本视为头文件,并将其导入到将调用其用户界面设计的文件中。 -
创建另一个名为
callAnimation1.pyw的 Python 文件,并将demoAnimation1.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import QRect, QPropertyAnimation
from demoAnimation1 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonMoveDown.clicked.connect(self.
startAnimation)
self.show()
def startAnimation(self):
self.anim = QPropertyAnimation(self.ui.labelPic,
b"geometry")
self.anim.setDuration(10000)
self.anim.setStartValue(QRect(160, 70, 80, 80))
self.anim.setEndValue(QRect(160, 70, 220, 220))
self.anim.start()
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
工作原理…
您可以看到,具有 objectName 属性pushButtonMoveDown的推送按钮小部件的 click()事件连接到startAnimation方法;当点击推送按钮时,将调用startAnimation方法。在startAnimation方法中,创建一个QPropertyAnimation类的对象并命名为anim。在创建QPropertyAnimation实例时,传递两个参数;第一个是要应用动画的标签小部件,第二个是定义要将动画应用于对象属性的属性。因为您想要对球的几何图形应用动画,所以在定义QPropertyAnimation对象时,将b"geometry"作为第二个属性传递。之后,将动画的持续时间指定为10000毫秒,这意味着您希望每隔 10,000 毫秒更改对象的几何图形。通过setStartValue方法,指定要开始动画的矩形区域,并通过调用setEndValue方法,指定要停止动画的矩形区域。通过调用start方法,启动动画;因此,球从通过setStartValue方法指定的矩形区域向下移动,直到达到通过setEndValue方法指定的矩形区域。
运行应用程序时,您会在屏幕上找到一个推送按钮和一个代表球图像的标签小部件,如下截图所示(左)。点击 Move Down 推送按钮后,球开始向地面动画,并在通过setEndValue方法指定的区域停止动画,如下截图所示(右):
制作一个弹跳的球
在这个示例中,您将制作一个弹跳的球;当点击按钮时,球向地面掉落,触及地面后,它会反弹到顶部。在这个示例中,您将了解如何在对象上应用基本动画。这个示例将包括一个推送按钮和一个球,当按下推送按钮时,球将开始向地面动画。
如何做…
要使球看起来像是在弹跳,我们需要首先使其向地面动画,然后从地面向天空动画。为此,我们将三次调用QPropertyAnimation类的setKeyValueAt方法。前两次调用setKeyValueAt方法将使球从顶部向底部动画。第三次调用setKeyValueAt方法将使球从底部向顶部动画。在三个setKeyValueAt方法中提供坐标,以使球以相反方向弹跳,而不是从哪里来的。以下是了解如何使球看起来像在弹跳的步骤:
-
基于没有按钮的对话框模板创建一个新的应用程序。
-
将一个标签小部件和一个推送按钮小部件拖放到表单上。
-
将推送按钮小部件的文本属性设置为
Bounce。我们假设您的计算机上有一个名为coloredball.jpg的球形图像。 -
要将球形图像分配给标签小部件,请选择其 pixmap 属性。
-
在 pixmap 属性中,从两个选项
Choose Resource和Choose File中选择Choose File选项,浏览您的磁盘,并选择coloredball.jpg文件。球的图像将出现在标签小部件的位置。 -
将推送按钮小部件的 objectName 属性设置为
pushButtonBounce,标签小部件的 objectName 属性设置为labelPic。 -
将应用程序保存为
demoAnimation3.ui。
应用程序将显示如下截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,这是一个 XML 文件,需要转换为 Python 代码。在应用pyuic5命令实用程序时,.ui文件将被转换为 Python 脚本。生成的 Python 脚本demoAnimation3.py可以在本书的源代码包中找到。
-
将
demoAnimation3.py脚本视为头文件,并将其导入到您将调用其用户界面设计的文件中。 -
创建另一个名为
callAnimation3.pyw的 Python 文件,并将demoAnimation3.py代码导入其中。
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import QRect, QPropertyAnimation
from demoAnimation3 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonBounce.clicked.connect(self.
startAnimation)
self.show()
def startAnimation(self):
self.anim = QPropertyAnimation(self.ui.labelPic,
b"geometry")
self.anim.setDuration(10000)
self.anim.setKeyValueAt(0, QRect(0, 0, 100, 80));
self.anim.setKeyValueAt(0.5, QRect(160, 160, 200, 180));
self.anim.setKeyValueAt(1, QRect(400, 0, 100, 80));
self.anim.start()
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
工作原理…
您可以看到,具有 objectName 属性pushButtonMoveDown的 Push 按钮小部件的 click()事件与startAnimation方法连接在一起;当单击按钮时,将调用startAnimation方法。在startAnimation方法中,您创建一个QPropertyAnimation类的对象,并将其命名为anim。在创建QPropertyAnimation实例时,您传递两个参数:第一个是要应用动画的 Label 小部件,第二个是定义要将动画应用于对象属性的属性。因为您想要将动画应用于球的几何属性,所以在定义QPropertyAnimation对象时,将b"geometry"作为第二个属性传递。之后,您将动画的持续时间指定为10000毫秒,这意味着您希望每隔 10,000 毫秒更改对象的几何形状。通过setKeyValue方法,您指定要开始动画的区域,通过这种方法指定左上角区域,因为您希望球从左上角向地面掉落。通过对setKeyValue方法的第二次调用,您提供了球掉落到地面的区域。您还指定了掉落的角度。球将对角线向下掉落到地面。通过调用第三个setValue方法,您指定动画停止的结束值,在这种情况下是在右上角。通过对setKeyValue方法的这三次调用,您使球对角线向下掉落到地面,然后反弹回右上角。通过调用start方法,您启动动画。
运行应用程序时,您会发现 Push 按钮和 Label 小部件代表球图像显示在屏幕左上角,如下面的屏幕截图所示(左侧)。
单击 Bounce 按钮后,球开始沿对角线向下动画移动到地面,如中间屏幕截图所示,触地后,球反弹回屏幕的右上角,如右侧所示:
根据指定的曲线使球动起来
创建一个具有所需形状和大小的曲线,并设置一个球在单击按钮时沿着曲线的形状移动。在这个示例中,您将了解如何实现引导动画。
如何做…
QPropertyAnimation类的setKeyValueAt方法确定动画的方向。对于引导动画,您在循环中调用setKeyValueAt方法。在循环中将曲线的坐标传递给setKeyValueAt方法,以使球沿着曲线动画。以下是使对象按预期动画的步骤:
-
基于无按钮对话框模板创建一个新的应用程序。
-
将一个 Label 小部件和一个 Push 按钮小部件拖放到表单上。
-
将 Push 按钮小部件的文本属性设置为
Move With Curve。 -
假设您的计算机上有一个名为
coloredball.jpg的球形图像,您可以使用其 pixmap 属性将此球形图像分配给 Label 小部件。 -
在
pixmap属性中,您会找到两个选项,选择资源和选择文件;选择选择文件选项,浏览您的磁盘,并选择coloredball.jpg文件。球的图像将出现在Label小部件的位置。 -
将
Push Button小部件的objectName属性设置为pushButtonMoveCurve,将Label小部件的objectName属性设置为labelPic。 -
将应用程序保存为
demoAnimation4.ui。应用程序将显示如下截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,是一个 XML 文件。通过应用pyuic5实用程序,将 XML 文件转换为 Python 代码。您可以在本书的源代码包中找到生成的 Python 代码demoAnimation4.py。
-
将
demoAnimation4.py脚本视为头文件,并将其导入到将调用其用户界面设计的文件中。 -
创建另一个名为
callAnimation4.pyw的 Python 文件,并将demoAnimation4.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import QRect, QPointF, QPropertyAnimation, pyqtProperty
from PyQt5.QtGui import QPainter, QPainterPath
from demoAnimation4 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonMoveCurve.clicked.connect(self.
startAnimation)
self.path = QPainterPath()
self.path.moveTo(30, 30)
self.path.cubicTo(30, 30, 80, 180, 180, 170)
self.ui.labelPic.pos = QPointF(20, 20)
self.show()
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
qp.drawPath(self.path)
qp.end()
def startAnimation(self):
self.anim = QPropertyAnimation(self.ui.labelPic, b'pos')
self.anim.setDuration(4000)
self.anim.setStartValue(QPointF(20, 20))
positionValues = [n/80 for n in range(0, 50)]
for i in positionValues:
self.anim.setKeyValueAt(i,
self.path.pointAtPercent(i))
self.anim.setEndValue(QPointF(160, 150))
self.anim.start()
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
工作原理…
首先,让曲线出现在屏幕上。这是将指导球动画的曲线;也就是说,它将作为动画的路径。您定义了QPainterPath类的实例并将其命名为path。您调用QPainterPath类的moveTo方法来指定路径或曲线的起始位置。调用cubicTo方法来指定球动画的曲线路径。
您会发现Push Button小部件的objectName属性为pushButtonMoveCurve的点击事件与startAnimation方法相连接;当单击Push Button小部件时,将调用startAnimation()方法。在startAnimation方法中,您创建了QPropertyAnimation类的对象并将其命名为anim。在创建QPropertyAnimation实例时,您传递了两个参数:第一个是要应用动画的Label小部件,第二个是定义要将动画应用于对象属性的属性。因为您想要将动画应用于球的位置,所以在定义QPropertyAnimation对象时,您将b'pos'作为第二个属性传递。之后,您将动画的持续时间指定为4000毫秒,这意味着您希望每4000毫秒更改球的位置。使用QPropertyAnimation类的setStartValue()方法,您指定了希望球进行动画的坐标。您设置了指定球需要沿着移动的值的for循环。您通过在for循环内调用setKeyValue方法来指定球的动画路径。因为球需要在路径中指定的每个点绘制,所以您通过调用pointAtPercent()方法并将其传递给setKeyValueAt()方法来设置球需要绘制的点。您还需要通过调用setEndValue()方法来设置动画需要停止的位置。
不久之后,您会指定动画的开始和结束位置,指定动画的路径,并调用paintEvent()方法来在路径的每一点重新绘制球。
运行应用程序后,您会在屏幕左上角(截图的左侧)找到Push Button小部件和代表球形图像的Label小部件,并在单击Move With Curve按钮后,球会沿着绘制的曲线开始动画,并在曲线结束的地方停止(截图的右侧):
第二十二章:使用谷歌地图
在本章中,您将学习如何在 Python 应用程序中使用谷歌地图,并探索谷歌提供的不同优势。您将学习以下任务:
-
查找位置或地标的详细信息
-
从经度和纬度值获取完整信息
-
查找两个位置之间的距离
-
在谷歌地图上显示位置
介绍
谷歌地图 API 是一组方法和工具,可用于查找任何位置的完整信息,包括经度和纬度值。您可以使用谷歌地图 API 方法查找两个位置之间的距离或到达任何位置的方向;甚至可以显示谷歌地图,标记该位置,等等。
更准确地说,谷歌地图服务有一个 Python“客户端”库。谷歌地图 API 包括方向 API、距离矩阵 API、地理编码 API、地理位置 API 等多个 API。要使用任何谷歌地图网络服务,您的 Python 脚本会向谷歌发送一个请求;为了处理该请求,您需要一个 API 密钥。您需要按照以下步骤获取 API 密钥:
-
使用您的谷歌账号登录控制台
-
选择您现有的项目之一或创建一个新项目。
-
启用您想要使用的 API
-
复制 API 密钥并在您的 Python 脚本中使用它
您需要访问谷歌 API 控制台,console.developers.google.com,并获取 API 密钥,以便您的应用程序经过身份验证可以使用谷歌地图 API 网络服务。
API 密钥在多个方面有帮助;首先,它有助于识别您的应用程序。API 密钥包含在每个请求中,因此它有助于谷歌监视您的应用程序的 API 使用情况,了解您的应用程序是否已经消耗完每日的免费配额,并因此向您的应用程序收费。
因此,为了在您的 Python 应用程序中使用谷歌地图 API 网络服务,您只需要启用所需的 API 并获取一个 API 密钥。
查找位置或地标的详细信息
在这个教程中,您将被提示输入您想要了解的位置或地标的详细信息。例如,如果您输入“白金汉宫”,该教程将显示宫殿所在地的城市和邮政编码,以及其经度和纬度值。
如何做…
GoogleMaps类的 search 方法是这个教程的关键。用户输入的地标或位置被传递给 search 方法。从 search 方法返回的对象的city、postal_code、lat和lng属性用于分别显示位置的城市、邮政编码、纬度和经度。让我们通过以下逐步过程来看看如何完成这个操作:
-
基于无按钮对话框模板创建一个应用程序。
-
通过将六个标签、一个行编辑和一个推送按钮小部件拖放到表单上,向表单添加六个标签、一个行编辑和一个推送按钮小部件。
-
将第一个标签小部件的文本属性设置为“查找城市、邮政编码、经度和纬度”,将第二个标签小部件的文本属性设置为“输入位置”。
-
删除第三、第四、第五和第六个标签小部件的文本属性,因为它们的文本属性将通过代码设置;也就是说,输入位置的城市、邮政编码、经度和纬度将通过代码获取并通过这四个标签小部件显示。
-
将推送按钮小部件的文本属性设置为“搜索”。
-
将行编辑小部件的 objectName 属性设置为
lineEditLocation。 -
将推送按钮小部件的 objectName 属性设置为
pushButtonSearch。 -
将其余四个标签小部件的 objectName 属性设置为
labelCity、labelPostalCode、labelLongitude和labelLatitude。 -
将应用程序保存为
demoGoogleMap1.ui。表单现在将显示如下屏幕截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,它是一个 XML 文件。通过应用pyuic5实用程序将 XML 文件转换为 Python 代码。您可以在本书的源代码包中找到生成的 Python 代码demoGoogleMap1.py。
-
将
demoGoogleMap1.py脚本视为头文件,并将其导入到将调用其用户界面设计的文件中。 -
创建另一个名为
callGoogleMap1.pyw的 Python 文件,并将demoGoogleMap1.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from geolocation.main import GoogleMaps
from demoGoogleMap1 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonSearch.clicked.connect(self.
displayDetails)
self.show()
def displayDetails(self):
address = str(self.ui.lineEditLocation.text())
google_maps = GoogleMaps(api_key=
'xxxxxxxxxxxxxxxxxxxxxxxxxxxx')
location = google_maps.search(location=address)
my_location = location.first()
self.ui.labelCity.setText("City:
"+str(my_location.city))
self.ui.labelPostalCode.setText("Postal Code: "
+str(my_location.postal_code))
self.ui.labelLongitude.setText("Longitude:
"+str(my_location.lng))
self.ui.labelLatitude.setText("Latitude:
"+str(my_location.lat))
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
它是如何工作的…
您可以在脚本中看到,具有 objectName 属性pushButtonSearch的按钮的单击事件连接到displayDetails方法。这意味着每当单击按钮时,将调用displayDetails方法。在displayDetails方法中,您访问用户在行编辑小部件中输入的位置,并将该位置分配给地址变量。通过传递在 Google 注册时获得的 API 密钥来定义 Google Maps 实例。在 Google Maps 实例上调用search方法,传递用户在此方法中输入的位置。search方法的结果分配给my_location结构。my_location结构的 city 成员包含用户输入的城市。类似地,my_location结构的postal_code、lng和lat成员分别包含用户输入位置的邮政编码、经度和纬度信息。城市、邮政编码、经度和纬度信息通过最后四个标签小部件显示。
运行应用程序时,将提示您输入要查找信息的位置。假设您在位置中输入泰姬陵,然后单击搜索按钮。泰姬陵地标的城市、邮政编码、经度和纬度信息将显示在屏幕上,如下面的屏幕截图所示:
从纬度和经度值获取完整信息
在本教程中,您将学习如何查找已知经度和纬度值的位置的完整详细信息。将点位置(即纬度和经度值)转换为可读地址(地名、城市、国家名称等)的过程称为反向地理编码。
应用程序将提示您输入经度和纬度值,然后显示匹配的位置名称、城市、国家和邮政编码。
如何做…
让我们根据以下步骤创建一个基于无按钮对话框模板的应用程序:
-
通过将七个
QLabel、两个QLineEdit和一个QPushButton小部件拖放到表单上,向表单添加七个标签、两个行编辑和一个按钮小部件。 -
将第一个标签小部件的文本属性设置为
查找位置、城市、国家和邮政编码,将第二个标签小部件的文本属性设置为输入经度,将第三个标签小部件的文本属性设置为输入纬度。 -
删除第四、第五、第六和第七个标签小部件的文本属性,因为它们的文本属性将通过代码设置;也就是说,用户输入经度和纬度的位置的位置、城市、国家和邮政编码将通过代码访问,并通过这四个标签小部件显示。
-
将 Push Button 小部件的文本属性设置为
搜索。 -
将两个行编辑小部件的 objectName 属性设置为
lineEditLongitude和lineEditLatitude。 -
将 Push Button 小部件的 objectName 属性设置为
pushButtonSearch。 -
将其他四个标签小部件的 objectName 属性设置为
labelLocation、labelCity、labelCountry和labelPostalCode。 -
将应用程序保存为
demoGoogleMap2.ui。表单现在将显示如下截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,这是一个 XML 文件,需要转换为 Python 代码。使用pyuic5实用程序将 XML 文件转换为 Python 代码。在本书的源代码包中可以看到生成的 Python 脚本demoGoogleMap2.py。
-
将
demoGoogleMap2.py脚本视为头文件,并将其导入到将调用其用户界面设计的文件中。 -
创建另一个名为
callGoogleMap2.pyw的 Python 文件,并将demoGoogleMap2.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from geolocation.main import GoogleMaps
from demoGoogleMap2 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonSearch.clicked.connect(self.
displayLocation)
self.show()
def displayLocation(self):
lng = float(self.ui.lineEditLongitude.text())
lat = float(self.ui.lineEditLatitude.text())
google_maps = GoogleMaps(api_key=
'AIzaSyDzCMD-JTg-IbJZZ9fKGE1lipbBiFRiGHA')
my_location = google_maps.search(lat=lat, lng=lng).
first()
self.ui.labelLocation.setText("Location:
"+str(my_location))
self.ui.labelCity.setText("City:
"+str(my_location.city))
self.ui.labelCountry.setText("Country:
"+str(my_location.country))
self.ui.labelPostalCode.setText("Postal Code:
"+str(my_location.postal_code))
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
操作原理如下:
在脚本中,您可以看到具有 objectName 属性pushButtonSearch的推送按钮的 click()事件连接到displayLocation方法。这意味着每当单击推送按钮时,将调用displayLocation方法。在displayLocation方法中,您通过两个 Line Edit 小部件访问用户输入的经度和纬度,并分别将它们分配给两个变量lng和lat。通过传递在 Google 注册时获得的 API 密钥来定义 Google Maps 实例。在 Google Maps 实例上调用search方法,传递用户提供的经度和纬度值。在检索到的搜索上调用first方法,并将与提供的经度和纬度值匹配的第一个位置分配给my_location结构。位置名称通过 Label 小部件显示。为了显示位置的城市、国家和邮政编码,使用my_location结构的city、country和postal_code成员。
运行应用程序时,您将被提示输入经度和纬度值。与提供的经度和纬度相关的位置名称、城市、国家和邮政编码将通过四个标签小部件显示在屏幕上,如下截图所示:
查找两个位置之间的距离
在这个教程中,您将学习如何找出用户输入的两个位置之间的距离(以公里为单位)。该教程将简单地提示用户输入两个位置,然后单击“查找距离”按钮,两者之间的距离将被显示。
操作步骤如下:
让我们根据没有按钮模板的对话框创建一个应用程序,执行以下步骤:
-
通过将四个标签、两个行编辑和一个推送按钮小部件拖放到表单上,向表单添加四个
QLabel、两个QLineEdit和一个QPushButton小部件。 -
将第一个标签小部件的文本属性设置为“查找两个位置之间的距离”,将第二个标签小部件的文本属性设置为“输入第一个位置”,将第三个标签小部件的文本属性设置为“输入第二个位置”。
-
删除第四个标签小部件的文本属性,因为它的文本属性将通过代码设置;也就是说,两个输入位置之间的距离将通过代码计算并显示在第四个标签小部件中。
-
将推送按钮小部件的文本属性设置为“查找距离”。
-
将两个行编辑小部件的 objectName 属性设置为
lineEditFirstLocation和lineEditSecondLocation。 -
将推送按钮小部件的 objectName 属性设置为
pushButtonFindDistance。 -
将第四个标签小部件的 objectName 属性设置为
labelDistance。 -
将应用程序保存为
demoGoogleMap3.ui。表单现在将显示如下截图所示:
使用 Qt Designer 创建的用户界面存储在.ui文件中,它是一个 XML 文件。通过应用pyuic5实用程序,将 XML 文件转换为 Python 代码。您可以在本书的源代码包中找到生成的 Python 代码demoGoogleMap3.py。
-
要使用在
demoGoogleMap3.py文件中创建的 GUI,我们需要创建另一个 Python 脚本并在该脚本中导入demoGoogleMap3.py文件。 -
创建另一个名为
callGoogleMap3.pyw的 Python 文件,并将demoGoogleMap3.py代码导入其中:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from googlemaps.client import Client
from googlemaps.distance_matrix import distance_matrix
from demoGoogleMap3 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonFindDistance.clicked.connect(self.
displayDistance)
self.show()
def displayDistance(self):
api_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
gmaps = Client(api_key)
data = distance_matrix(gmaps,
self.ui.lineEditFirstLocation.text(),
self.ui.lineEditSecondLocation.text())
distance = data['rows'][0]['elements'][0]['distance']
['text']
self.ui.labelDistance.setText("Distance between
"+self.ui.lineEditFirstLocation.text()+"
and "+self.ui.lineEditSecondLocation.text()+" is
"+str(distance))
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
它是如何工作的…
您创建一个Client类的实例并将其命名为gmaps。在创建Client实例时,您需要传递在注册 Google 时获得的 API 密钥。具有 objectNamepushButtonFindDistance的按钮的 click()事件连接到displayDistance方法。这意味着每当单击按钮时,将调用displayDistance方法。在displayDistance方法中,您调用distance_matrix方法,传递Client实例和用户输入的两个位置,以找出它们之间的距离。distance_matrix方法返回一个多维数组,该数组分配给数据数组。从数据数组中,访问并将两个位置之间的距离分配给distance变量。最终通过 Label 小部件显示distance变量中的值。
运行应用程序时,将提示您输入要了解其相隔距离的两个位置。输入两个位置后,单击查找距离按钮,两个位置之间的距离将显示在屏幕上,如下截图所示:
在 Google 地图上显示位置
在本教程中,您将学习如何在 Google 地图上显示位置,如果您知道该位置的经度和纬度值。您将被提示简单输入经度和纬度值,当您单击显示地图按钮时,该位置将显示在 Google 地图上。
如何做…
让我们创建一个基于无按钮对话框模板的应用程序,执行以下步骤:
-
通过将两个 Label、两个 Line Edit、一个 PushButton 和一个 QWidget 小部件拖放到表单上,向表单添加两个 QLabel、两个 QLineEdit、一个 QPushButton 和一个 QWidget 小部件。
-
将两个 Label 小部件的文本属性设置为
Longitude和Latitude。 -
将 Push Button 小部件的文本属性设置为
Show Map。 -
将两个 Line Edit 小部件的 objectName 属性设置为
lineEditLongitude和lineEditLatitude。 -
将 Push Button 小部件的 objectName 属性设置为
pushButtonShowMap。 -
将应用程序保存为
showGoogleMap.ui。现在,表单将显示如下截图所示:
-
下一步是将
QWidget小部件提升为QWebEngineView,因为要显示 Google 地图,需要QWebEngineView。因为 Google 地图是一个 Web 应用程序,我们需要一个 QWebEngineView 来显示和与 Google 地图交互。 -
通过右键单击 QWidget 小部件并从弹出菜单中选择 Promote to …选项来提升
QWidget小部件。在出现的对话框中,将 Base class name 选项保留为默认的 QWidget。 -
在 Promoted class name 框中输入
QWebEngineView,在 header file 框中输入PyQT5.QtWebEngineWidgets。 -
单击 Promote 按钮,将
QWidget小部件提升为QWebEngineView类,如下截图所示:
-
单击关闭按钮关闭 Promoted Widgets 对话框。使用 Qt Designer 创建的用户界面存储在
.ui文件中,这是一个 XML 文件,需要转换为 Python 代码。使用pyuic5实用程序将 XML 文件转换为 Python 代码。生成的 Python 脚本showGoogleMap.py可以在本书的源代码包中找到。 -
将
showGoogleMap.py脚本视为头文件,并将其导入到您将调用其用户界面设计的文件中。 -
创建另一个名为
callGoogleMap.pyw的 Python 文件,并将showGoogleMap.py代码导入其中:
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QDialog
from PyQt5.QtWebEngineWidgets import QWebEngineView
from showGoogleMap import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButtonShowMap.clicked.connect(self.dispSite)
self.show()
def dispSite(self):
lng = float(self.ui.lineEditLongitude.text())
lat = float(self.ui.lineEditLatitude.text())
URL="https://www.google.com/maps/@"+self.ui.
lineEditLatitude.text()+","
+self.ui.lineEditLongitude.text()+",9z"
self.ui.widget.load(QUrl(URL))
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
工作原理…
在脚本中,您可以看到具有 objectName 属性pushButtonShowMap的按钮的点击事件与dispSite()方法相连。这意味着,每当点击按钮时,将调用dispSite()方法。在dispSite()方法中,您通过两个 Line Edit 小部件访问用户输入的经度和纬度,并分别将它们分配给两个变量lng和lat。然后,您创建一个 URL,从google.com调用 Google 地图,并传递用户输入的纬度和经度值。
URL 最初是以文本形式存在的,并且被强制转换为QUrl实例,并传递给被提升为QWebEngineView以显示网站的小部件。QUrl是 Qt 中提供多种方法和属性来管理 URL 的类。然后,通过QWebEngineView小部件显示具有指定纬度和经度值的 Google 地图。
运行应用程序时,您将被提示输入您想在 Google 地图上查看的位置的经度和纬度值。输入经度和纬度值后,当您点击“显示地图”按钮时,Google 地图将显示该位置,如下面的屏幕截图所示:
更多推荐



所有评论(0)