用 python pyqt 手把手写一个b站常见的数据可视化的框架(一)

最近b站上有不少数据可视化的视频,
用 python pyqt 手把手写一个b站常见的数据可视化的框架(一)_第1张图片
据说基本上都是由 Jannchie见齐 大佬的框架制作的,听说这个框架用起来很方便(虽然我暂时还没用过),不过这么多人用那就表示做的相当好,但是我的毕设是自己搞一个数据可视化系统,毕设总不能拿别人的吧,所以我就干脆搞一个类似的做毕设得了,
话说我舍友也是b站up主,一直吐槽自己辛苦做的mad没人看,别人导几个数据进去就有几十万播放(做mad死路一条.jpg)

用qt就可以了,昨天开始做的,现在还是个半成品,界面很简陋,这几天会完善好,喜欢的可以去github上给个star
先给大家眼睛道个歉
用法还是很简单的,传一个字典进去,字典中每一个key对应一个list,list中储存值的变化,可以设置最大显示数量,和动画时间,和左侧的标签属性,不设置默认为text,以后还可以设置更多花样,这几天会搞定
用 python pyqt 手把手写一个b站常见的数据可视化的框架(一)_第2张图片

演示效果
()用 python pyqt 手把手写一个b站常见的数据可视化的框架(一)_第3张图片
写一下制作过程(只是个半成品正在完善),先说最基本的
先说一下QPropertyAnimation,可以自定义控件的变化与时间

@pyqtSlot()
def on_pushButton_clicked(self):
    self.label = QtWidgets.QLabel(self)
    self.label.setGeometry(QtCore.QRect(150, 142, 141, 141))
    self.label.setStyleSheet("background-color: rgb(119, 78, 255);") 
    self.label.show()
    self.anim = QPropertyAnimation(self.label, b"geometry")#操作self.label
    self.anim.setDuration(1000)#动画时间10s
    self.anim.setStartValue(QtCore.QRect(150, 142, 141, 141))#起始位置
    self.anim.setKeyValueAt(0.5, QtCore.QRect(150, 80, 141, 141))#50%时的位置
    self.anim.setEndValue(QtCore.QRect(60, 80, 141, 141))#结束位置
    self.anim.start()

1首先写一个界面,为了方便观察背景设为白色,加一个按钮用来开始

用 python pyqt 手把手写一个b站常见的数据可视化的框架(一)_第4张图片

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(1000, 890)
        Dialog.setSizeGripEnabled(True)
        self.setStyleSheet("background-color: rgb(255, 255, 255)")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(50, 800, 100, 50))
        self.pushButton.setObjectName("pushButton")
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):

        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.pushButton.setText(_translate("Dialog", "开始吧"))

2写一个随参数变化位置与长度的条
在这里插入图片描述
就是见齐大佬视频里的这个啦,这个条可以通过Qlabel实现,设置其底色为红即可
负责计算每个条的xywl(x,y,width,lenght即位置与大小)等参数的函数以后再说,先默认其是计算好的,
xywl_list表示在移动过程中依次要去的位置,
time为动画时间,未定义默认为每次变化一秒
color为背景颜色,为了方便演示默认为黑色了
text为显示文本,先不管了默认为‘’
show_num为只显示前show_num名
继承Qlabel

class bar_label(QLabel):
        def __init__(self, xywl, xywl_list,ui, show_num,  time=None, text='',color=None ):
            super(bar_label, self).__init__(ui)
            self.x, self.y, self.w, self.l=xywl
            self.xywl_list=xywl_list
            self.show_num=show_num
            if time==None:time=1000*len(xywl_list)#没有设置时间就一秒设置一次
            self.time=time
            self.color=color
            self.setGeometry(QtCore.QRect(0, self.y, self.l, self.l))
            self.setStyleSheet("background-color: rgb"+str((0, 0, 0))+";font-size:"+str(300//show_num)+"px")#这里以后会改的
            self.setText(text)
            self.show() 

移动函数

 def  move_it(self):
      n=len(self.xywl_list)
      self.anim = QPropertyAnimation(self, b"geometry")
      self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
      self.anim.setDuration(self.time)
      for i in range(n):
            x, y, w, l=self.xywl_list[i]
            self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
      self.anim.start()

随参数变化效果如下
代码

w=   [(100, 0, 775, 90), (100, 560, 300, 90), (100, 0, 515, 90), (100, 420, 380, 90), (100, 140, 660, 90), (100, 140, 560, 90), (100, 280, 350, 90), (100, 280, 515, 90), (100, 140, 445, 90), (100, 560, 355, 90)]
s=bar_label(w[0], w[1:], self, 5, 10000)#self是窗口
s.move_it()


3写一个随参数变化位置与数字的标签
在这里插入图片描述
就是见齐大佬视频里的这个啦,还是继承qlabel

class num_label(QLabel):
        def __init__(self, xywl, xywl_list,ui, show_num, num_list,  time=None,color=None ):
           super(num_label, self).__init__(ui)
           self.x, self.y, self.w, self.l=xywl
           self.x=self.x+self.w+50#跟在条的后面
           self.time=time
           self.color=color
           self.w=200
           self.xywl_list=xywl_list
           self.show_num=show_num
           self.num_list=num_list#记录参数
           self.setGeometry(QtCore.QRect(self.x, self.y, self.l, self.l))
           self.setStyleSheet("background-color: rgb"+str((255, 255, 255))+";font-size:15px")

           self.setText(str(num_list[0]))#开始值
           self.show()

为了支持数字动态变化

 def get_num(self):
            return 0 
 def set_num(self, s):
            self.setText(str(s))
 text = pyqtProperty(int, fget=get_num, fset=set_num)

这样
self.anim = QPropertyAnimation(self, b"text")会调用set_num
变化函数

 def  move_it(self):
       n=len(self.xywl_list)
      self.anim = QPropertyAnimation(self, b"geometry")
      self.anim2 = QPropertyAnimation(self, b"text")
               
       self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
       self.anim.setDuration(self.time)
       self.anim2.setDuration(self.time)  
       for i in range(n):
            x, y, w, l=self.xywl_list[i]
            x=x+w+50#跟在条后面
            w=200
            self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
       for i in range(1,  n-1):
                self.anim2.setKeyValueAt((i)/len(self.xywl_list), self.num_list[i])
       self.anim2.setEndValue(self.num_list[-1])
       self.anim.start()
       self.anim2.start()

4写一个随参数变化位置且可以设定文本或图片的标签
还是继承qlabel
label_type默认为’text‘,为’pic‘时,会将text识别为图片路径

class labels_label(QLabel):
    def __init__(self, xywl, xywl_list,ui, show_num, time=None, label_type='text'  ,text='example',color=None ):
       super(labels_label, self).__init__(ui)
       self.x, self.y, self.w, self.l=xywl
       self.x=0#在最左侧
       self.time=time
       self.text=text
       self.color=color
       self.label_type=label_type
       self.w=100
       self.xywl_list=xywl_list
       self.show_num=show_num
       self.setGeometry(QtCore.QRect(0, self.y, self.l, self.l))
       self.setStyleSheet("background-color: rgb"+str((255, 255, 255))+";font-size:15px")
       self.setObjectName(text)
       if self.label_type=='text':self.setText(text)
       else:
         img=QPixmap(text)
         self.setScaledContents(True) 
         self.setPixmap(img)
         self.show() 

移动函数

   def  move_it(self):
            n=len(self.xywl_list)
            self.anim = QPropertyAnimation(self, b"geometry")
            self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
            self.anim.setDuration(self.time)
            for i in range(n):
                x, y, w, l=self.xywl_list[i]
                x=0
                w=100
                self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
            self.anim.start()

效果如下
计算每个条的移动轨迹的函数下次说
这一部分完整代码

import sys, random
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import  QApplication, QLabel,QDialog
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(1000, 890)
        Dialog.setSizeGripEnabled(True)
        self.setStyleSheet("background-color: rgb(255, 255, 255)")
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(50, 800, 100, 50))
        self.pushButton.setObjectName("pushButton")
        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.pushButton.setText(_translate("Dialog", "开始吧"))
class Dialog(QDialog, Ui_Dialog):
    def __init__(self,  parent=None):
        super(Dialog, self).__init__(parent)
        self.setupUi(self)
    @pyqtSlot()
    def on_pushButton_clicked(self):
        q={'A': [(100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0)], 'B': [(100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0)], 'C': [(100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0)], 'D': [(100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 420, 260, 90), (100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0)], 'E': [(100, 800, 0, 0), (100, 800, 0, 0), (100, 800, 0, 0), (100, 560, 300, 90), (100, 800, 0, 0), (100, 800, 0, 0), (100, 560, 195, 90), (100, 800, 0, 0), (100, 420, 240, 90), (100, 280, 385, 90)], 'F': [(100, 560, 300, 90), (100, 420, 480, 90), (100, 140, 440, 90), (100, 140, 460, 90), (100, 560, 395, 90), (100, 280, 495, 90), (100, 800, 0, 0), (100, 560, 380, 90), (100, 280, 275, 90), (100, 420, 360, 90)], 'G': [(100, 140, 590, 90), (100, 280, 505, 90), (100, 280, 420, 90), (100, 280, 455, 90), (100, 420, 565, 90), (100, 560, 345, 90), (100, 800, 0, 0), (100, 420, 425, 90), (100, 800, 0, 0), (100, 800, 0, 0)], 'H': [(100, 420, 365, 90), (100, 0, 580, 90), (100, 560, 365, 90), (100, 800, 0, 0), (100, 280, 630, 90), (100, 420, 455, 90), (100, 0, 620, 90), (100, 0, 645, 90), (100, 0, 515, 90), (100, 140, 520, 90)], 'I': [(100, 0, 775, 90), (100, 560, 300, 90), (100, 0, 515, 90), (100, 420, 380, 90), (100, 140, 660, 90), (100, 140, 560, 90), (100, 280, 350, 90), (100, 280, 515, 90), (100, 140, 445, 90), (100, 560, 355, 90)], 'J': [(100, 280, 505, 90), (100, 140, 580, 90), (100, 420, 380, 90), (100, 0, 850, 90), (100, 0, 890, 90), (100, 0, 730, 90), (100, 140, 450, 90), (100, 140, 645, 90), (100, 560, 240, 90), (100, 0, 775, 90)]}
        q2={'A': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'B': [14, 13, 17, 8, 19, 11, 17, 13, 19, 6], 'C': [33, 40, 33, 23, 31, 30, 35, 15, 14, 17], 'D': [21, 51, 53, 39, 58, 45, 21, 59, 60, 23], 'E': [72, 37, 24, 32, 42, 46, 46, 64, 66, 60], 'F': [32, 35, 86, 84, 52, 38, 55, 39, 53, 94], 'G': [39, 111, 112, 45, 58, 92, 95, 78, 50, 90], 'H': [85, 93, 43, 61, 117, 57, 51, 120, 84, 93], 'I': [67, 97, 152, 146, 76, 54, 81, 95, 108, 71], 'J': [126, 51, 135, 170, 64, 152, 123, 120, 114, 173]}
        labels=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
        l1=[]
        l2=[]
        l3=[]
        for i in range(len(labels)):
            l1.append(labels_label(q[labels[i]][0], q[labels[i]][1:], self, 5, 10000, 'text',text= labels[i]))
            l2.append(bar_label(q[labels[i]][0], q[labels[i]][1:], self, 5, 10000))
            l3.append(num_label(q[labels[i]][0], q[labels[i]][1:], self, 5,q2[labels[i]],  10000))
        for i in  range(len(labels)):
            l1[i].move_it()
            l2[i].move_it()
            l3[i].move_it()
class bar_label(QLabel):
        def __init__(self, xywl, xywl_list,ui, show_num,  time=None, text='',color=None ):
            super(bar_label, self).__init__(ui)
            self.x, self.y, self.w, self.l=xywl
            self.xywl_list=xywl_list
            self.show_num=show_num
            if time==None:time=1000*len(xywl_list)
            self.time=time
            self.text=text
            self.color=color
            self.setGeometry(QtCore.QRect(0, self.y, self.l, self.l))
            self.setStyleSheet("background-color: rgb"+str((random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) ))+";font-size:"+str(300//show_num)+"px")
            self.setObjectName(text)
            self.setText(text)
            self.show() 
        def  move_it(self):
            n=len(self.xywl_list)
            self.anim = QPropertyAnimation(self, b"geometry")
            self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
            self.anim.setDuration(self.time)
            for i in range(n):
                x, y, w, l=self.xywl_list[i]
                self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
            self.anim.start()
class labels_label(QLabel):
     def __init__(self, xywl, xywl_list,ui, show_num, time=None, label_type='text'  ,text='example',color=None ):
           super(labels_label, self).__init__(ui)
           self.x, self.y, self.w, self.l=xywl
           self.x=0
           self.time=time
           self.text=text
           self.color=color
           self.label_type=label_type
           self.w=min(self.l+300//show_num*len(text), 100)
           self.xywl_list=xywl_list
           self.show_num=show_num
           self.setGeometry(QtCore.QRect(self.x, self.y, self.l, self.l))
           self.setStyleSheet("background-color: rgb"+str((255, 255, 255))+";font-size:15px")
           self.setObjectName(text)
           if self.label_type=='text':self.setText(text)
           else:
               img=QPixmap(text)
               self.setScaledContents(True) 
               self.setPixmap(img)
           self.show() 
     def  move_it(self):
            n=len(self.xywl_list)
            self.anim = QPropertyAnimation(self, b"geometry")
            self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
            self.anim.setDuration(self.time)
            for i in range(n):
                x, y, w, l=self.xywl_list[i]
                x=0
                w=min(l+300//self.show_num*len(self.text), 100)
                self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
            self.anim.start()
class num_label(QLabel):
        def __init__(self, xywl, xywl_list,ui, show_num, num_list,  time=None,color=None ):
           super(num_label, self).__init__(ui)
           self.x, self.y, self.w, self.l=xywl
           self.x=self.x+self.w+50
           self.time=time
           self.color=color
           self.w=200
           self.xywl_list=xywl_list
           self.show_num=show_num
           self.num_list=num_list
           self.setGeometry(QtCore.QRect(self.x, self.y, self.l, self.l))
           self.setStyleSheet("background-color: rgb"+str((255, 255, 255))+";font-size:15px")
           self.setText(str(num_list[0]))
           self.show() 
        def get_num(self):
            return 0 
        def set_num(self, s):
            self.setText(str(s))
        text = pyqtProperty(int, fget=get_num, fset=set_num) 
        def  move_it(self):
            n=len(self.xywl_list)
            self.anim = QPropertyAnimation(self, b"geometry")
            self.anim2 = QPropertyAnimation(self, b"text")
            self.anim.setStartValue(QRect(self.x,self.y, self.w, self.l));
            self.anim.setDuration(self.time)
            self.anim2.setDuration(self.time)  
            for i in range(n):
                x, y, w, l=self.xywl_list[i]
                x=x+w+50
                w=200
                self.anim.setKeyValueAt((i+1)/len(self.xywl_list), QRect(x,y, w, l))
            for i in range(1,  n-1):
                self.anim2.setKeyValueAt((i)/len(self.xywl_list), self.num_list[i])
            self.anim2.setEndValue(self.num_list[-1])
            self.anim.start()
            self.anim2.start()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    dlg = Dialog()
    dlg.show()
    sys.exit(app.exec_())

你可能感兴趣的:(用 python pyqt 手把手写一个b站常见的数据可视化的框架(一))