重工电子论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 5821|回复: 0

PyQt实现简单汽车仪表盘(一)

[复制链接]

15

主题

24

帖子

379

积分

学生管理组

Rank: 8Rank: 8

积分
379
发表于 2017-11-20 22:41:55 | 显示全部楼层 |阅读模式
本帖最后由 刘鑫-15电子 于 2017-11-20 22:41 编辑

最近做一个汽车仪表盘的项目,用到Pyqt5,于是我决定开贴,记录我的实现路程:

        首先我在做的时候,首先考虑的就是我们要用什么来实现UI编程,我本来想的是用C#,但是由于这段时间在学python,而且,最终我们是应用在Linux上,所以我决定用python来写,得益于python丰富多样的资源。
python社区为我们提供了多种UI的编程方式,在选择之后,我最后选择了使用python下的Qt来进行开发。Qt这个东西原本是基于C++来开发的,但是python社区做了一个可以用python来实现Qt的工具包,名为PyQt
我们首先要搭载PyQt的环境,这个在网上非常多的教程,pycharm下PyQt5等等方式都可以搜索到的。我建议大家都用Anaconda,非常方便。
        我选择的是PyQt5,有个问题就是,现在PyQt5的资料不是很丰富,所以必选要结合Qt来学习,这花了我很长一段时间。这里我先给出一个相对比较官方的文档链接给大家:https://pythonspot.com/en/pyqt5/  。这个文档里面有很多的简单控件的应用实例,所以还是比较好的。      当所有的环境配置好之后,可以先写一些简单的程序来熟悉一下基本的控件,在设计的时候可以用QtDesigner来进行简单的辅助设计,对于QtDesigner大家可以自己搜一下教程,很多,也算是比较简单,就是拖控件。
割割割割割割割割割割割割割割割割割割割割割。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
      现在呢,进入我们的主题,开始设计我们的仪表盘。关于仪表盘,我遇到的第一个问题就是指针的旋转问题,首先仪表盘本身我实际是找个这样的一张图片。贴上我的酷炫神图:
20161230203312122.png


但是有一个问题。。。这张图有太多的我们不想要的东西,比如仪表盘上的指针,使我们需要取消的,因为我们最后的指针是需要我们画上去的,可以旋转的。还有哪些多余的文字。
我这个人比较糙,也不会什么PS,于是我用了最简单的方法,就是用的电脑上的画图。
AF74F41H2QVEP`8K[@BP%(5.png



我把图片放到最大,然后用橡皮擦将不用的擦掉,然后使用背景色进行填充或者用画笔画上。
最后我做出了这样的图片:
仪表盘.png

这就是我们的素材了。
简单,暴力。
然后我们需要将我们的图片设置成我们窗口的桌面背景。
贴上我实现桌面背景的方法。
[Python] syntaxhighlighter_viewsource syntaxhighlighter_copycode
    #设置桌面背景[/size]
[size=4]    def setBackground(self):[/size]
[size=4]        painter =QPainter(self)[/size]
[size=4]        painter.setRenderHint(QPainter.Antialiasing)  # 绘制图像反锯齿[/size]
[size=4]        pix=QPixmap("./Image/仪表盘.png")[/size]
[size=4]        pix=pix.scaled(self.width(),self.height(),Qt.KeepAspectRatio)[/size]
[size=4]        painter.drawPixmap(self.rect(),pix)

[Python] syntaxhighlighter_viewsource syntaxhighlighter_copycode
    # #重写paintEvent[/size]
[size=4]    def paintEvent(self, event):[/size]
[size=4]        self.setBackground()

我们重写绘制事件,保证我们的窗口可以随着窗口改变而改变。实际上,我们实现桌面背景的方式有很多,可以用Qlebal的方式,QLebal是一个非常强大的控件,可以嵌入富文本,图片等等,具体的用法我就不多说,我也不够娴熟。
现在我们想在仪表盘上添上我们的指针。
对于指针,我也是想了很多办法,比如直接用画笔也就是QPainter直接用画笔来画,但是我试了下,按照我的技术,画出来实在是不太好看,最后我选择了另一种方式,就是指针也用图片来实现。
在Qt当中实际上提供了一个非常强大的旋转功能,它是以坐标旋转来完成的,在绘制过程中通过旋转坐标,而使得我们图片的方向发生一个改变。最后绘制完之后又重新恢复坐标,使我们其他的操作不会受到影响。
上述的就是我们的思想,但是真的要绘制一个指针的旋转还是比较麻烦的,为了好看,并且能够达到我们想要的效果,于是,我找洋哥(刘洋)用它高超的P图技术,帮我在一张仪表图上扣了一个指针下来,然后扣下来的图如下,(实际上是只把这个图案扣下来了,利用png格式的话,除指针以外的地方都是透明的,这样我们就不会贴上一个图片后,覆盖了后面的表盘)
Pointery.png Poniter.png 实际上这张图黑色的部分都是没有的,透明的。



然后我们素材搞定了,接下来呢,我们需要计算好我们的旋转中心,也就是我们的表盘的中心,这个位置不是我们整张图片或者是整个窗口的中心,而是我们表盘的圆心所在坐标。计算好之后,我们使用translate函数将我们窗口的坐标原点转换为我们的圆心点,并且将我们指针这张图片的圆心移动到这里,使我们的仪表盘的圆心、窗口坐标原点、以及指针的圆心重合,只有这样,我们在旋转的时候,才能对。
以下是我的定位坐标,并且旋转的代码。

[Python] syntaxhighlighter_viewsource syntaxhighlighter_copycode
    #速度指针[/size]
[size=4]    def drawspeedPoniter(self,angle):[/size]
[size=4]        painter =QPainter(self)[/size]
[size=4]        painter.setRenderHint(QPainter.Antialiasing)  #绘制图像反锯齿[/size]
[size=4]        painter.translate(960,350)#将坐标重新放置在窗口中央[/size]
[size=4]        painter.save()[/size]
[size=4]        painter.rotate(angle)[/size]
[size=4]        #计算大小以及坐标[/size]
[size=4]        painter.drawPixmap(-self.pointer.width()/2.8/2,-43,self.pointer.width()/2.8,self.pointer.height()/2.8,self.pointer)[/size]
[size=4]        painter.restore()



最后在这里有一个用法是需要注意的,就是,我们的指针图片的尺寸可能并不是我们想的匹配我们的表盘,这时候你可以在设置大小的时候,进行一个比例缩小或者放大(尽量找大一点的图片,然后缩小)。其中,roate()函数就是坐标的旋转函数。参数为顺时针角度。


贴上我的完整代码:
[Python] syntaxhighlighter_viewsource syntaxhighlighter_copycode
class CarInstrument(QWidget):[/size]
[size=4]    def __init__(self):[/size]
[size=4]        super().__init__()[/size]
[size=4]        self.setWindowFlags(Qt.FramelessWindowHint)#设置为无边框[/size]

[size=4]        self.setspeedPointer()#创造指针[/size]
[size=4]        self.getdim()#获取敏感尺寸[/size]
[size=4]        self.resize(1920,720)#设置为图片的大小[/size]
[size=4]        # self.showMaximized()[/size]
[size=4]        # self.setBackground()[/size]
[size=4]        # self.setStyle("#border-image:url(:/Image/仪表盘.png)")[/size]
[size=4]        self.SetTimer()   #开一个定时器来进行自动旋转演示[/size]
[size=4]     #初始化UI[/size]
[size=4]    def setUI(self):[/size]
[size=4]        pass[/size]
[size=4]    def showMaximized(self):[/size]
[size=4]        desktop =QApplication.desktop()[/size]
[size=4]        rect =desktop.availableGeometry()[/size]
[size=4]        self.setGeometry(rect)[/size]
[size=4]    def SetTimer(self):[/size]
[size=4]        self.timer =QTimer(self)[/size]
[size=4]        self.timer.timeout.connect(self.update)[/size]
[size=4]        self.angle=0[/size]
[size=4]        self.timer.start(50)[/size]



[size=4]    #设置桌面背景[/size]
[size=4]    def setBackground(self):[/size]
[size=4]        painter =QPainter(self)[/size]
[size=4]        painter.setRenderHint(QPainter.Antialiasing)  # 绘制图像反锯齿[/size]
[size=4]        pix=QPixmap("./Image/仪表盘.png")[/size]
[size=4]        pix=pix.scaled(self.width(),self.height(),Qt.KeepAspectRatio)[/size]
[size=4]        painter.drawPixmap(self.rect(),pix)[/size]




[size=4]    # #重写paintEvent[/size]
[size=4]    def paintEvent(self, event):[/size]
[size=4]        self.setBackground()[/size]
[size=4]        self.angle+=1[/size]
[size=4]        if(self.angle>360):[/size]
[size=4]            self.angle=0[/size]
[size=4]        self.drawspeedPoniter(self.angle)[/size]




[size=4]    def setspeedPointer(self):[/size]
[size=4]        self.pointer = QPixmap()  #创建一个pixmap对象[/size]
[size=4]        self.pointer.load("./Image/Pointery.png")[/size]

[size=4]    #速度指针[/size]
[size=4]    def drawspeedPoniter(self,angle):[/size]
[size=4]        painter =QPainter(self)[/size]
[size=4]        painter.setRenderHint(QPainter.Antialiasing)  #绘制图像反锯齿[/size]
[size=4]        painter.translate(960,350)#将坐标重新放置在窗口中央[/size]
[size=4]        painter.save()[/size]
[size=4]        painter.rotate(angle)[/size]
[size=4]        #计算大小以及坐标[/size]
[size=4]        painter.drawPixmap(-self.pointer.width()/2.8/2,-43,self.pointer.width()/2.8,self.pointer.height()/2.8,self.pointer)[/size]
[size=4]        painter.restore()[/size]
[size=4]    #计算尺寸[/size]
[size=4]    def cdim(self):[/size]
[size=4]        pass[/size]
[size=4]        # widproportion =self.geometrywidth/self.pointer_width[/size]
[size=4]        # hitproportion =self.geometryheight/self.pointer_height[/size]




[size=4]    #获取各种各样的尺寸[/size]
[size=4]    def getdim(self):[/size]
[size=4]        #获取屏幕尺寸[/size]
[size=4]        thisgeometry = self.geometry()[/size]
[size=4]        self.geometrywidth =thisgeometry.width()[/size]
[size=4]        self.geometryheight=thisgeometry.height()[/size]
[size=4]        #获取背景图片尺寸[/size]
[size=4]        # self.back_width =self.pointer.width()[/size]
[size=4]        # self.back_height=self.pointer.height()[/size]
[size=4]        #获取图标指针图片尺寸[/size]
[size=4]        self.pointer_width=self.pointer.width()[/size]
[size=4]        self.pointer_height=self.pointer.height()[/size]









[size=4]if __name__ == '__main__':[/size]
[size=4]    app = QApplication(sys.argv)[/size]
[size=4]    ex = CarInstrument()[/size]
[size=4]    ex.show()[/size]
[size=4]    sys.exit(app.exec_())


贴上我最后的效果图:

2.png
1.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|cqutlab ( 渝ICP备15004556号

GMT+8, 2024-3-29 01:21 , Processed in 0.182102 second(s), 34 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表