重工电子论坛

标题: PyQt实现简单汽车仪表盘(一) [打印本页]

作者: 刘鑫-15电子    时间: 2017-11-20 22:41
标题: PyQt实现简单汽车仪表盘(一)
本帖最后由 刘鑫-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大家可以自己搜一下教程,很多,也算是比较简单,就是拖控件。
割割割割割割割割割割割割割割割割割割割割割。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
      现在呢,进入我们的主题,开始设计我们的仪表盘。关于仪表盘,我遇到的第一个问题就是指针的旋转问题,首先仪表盘本身我实际是找个这样的一张图片。贴上我的酷炫神图:



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




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


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

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

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



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

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



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


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

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



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




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




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

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




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









if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = CarInstrument()
    ex.show()
    sys.exit(app.exec_())


贴上我最后的效果图:


1.png (692.14 KB, 下载次数: 1251)

1.png





欢迎光临 重工电子论坛 (http://cqutlab.cn/) Powered by Discuz! X3.1