@


一.前言

本次将之前做的和新做的轮播图Demo进行展示。废话不多说,直接上图

二.展示

1.酷我音乐

数据源:网络
格式:接口Json
参考网站:http://www.kuwo.cn/
支持自动、手动切换,导航栏切换图片
请添加图片描述

2.QQ飞车

数据源:网络
格式:接口Json
参考网站:数据来源QQ飞车客户端抓包
官网:http://speed.qq.com/main.shtml
支持自动、手动切换,导航栏切换图片(右上角那个不规则按钮还不能实现)
请添加图片描述

3.虎牙

数据源:网络
格式:接口Json
参考网站:https://www.huya.com/
支持自动、手动切换,导航栏、左右按钮切换图片
请添加图片描述

4.网易云音乐

数据源:本地
格式:列表
参考网站:https://music.163.com/
支持自动、手动切换,导航栏、左右按钮切换图片,轮播图切换动画为淡出
请添加图片描述

5.英雄联盟

数据源:本地
格式:列表
参考网站:https://lol.qq.com/main.shtml
支持自动、手动切换,导航栏切换图片,轮播图切换动画为正弦缓入
请添加图片描述

6.英雄联盟(Pro)

在上一个的基础上进行改进,重写QStackWidget的SetCurrentInex()函数,实现了过渡动画的显示
请添加图片描述

7.腾讯视频

数据源:本地
格式:列表
参考网站:https://v.qq.com/
这个上了点难度,不过只要慢慢拆解,还是不难的。
支持自动、手动切换,导航栏切换图片,支持手动切换推荐视频
请添加图片描述

值得一提的是,“猜你会追”页面有个子页面,里面是一些电影、电视剧推荐,要通过按钮手动切换推荐,鼠标放在推荐上,封面会自动放大(注意“下一张”按钮位置)。

请添加图片描述动图被压缩了,可能看不太清,贴一张静图。
在这里插入图片描述


三.源代码

贴一下demo3的代码

1.demo02GUI.py

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from CWidgets import ClickQLabel,CPushButton

"""
游戏推荐轮播图
"""
from engine import HuyaSpider, MyTools

ROTATION_WIDTH = 900  # widget宽度
ROTATION_HEIGHT = 180  # widget高度


class CRotaion_widget(QWidget):
    load_finish_singal = pyqtSignal()
    ratationClicked_signal = pyqtSignal(str)

    def __init__(self, type, recommends, widthSize, heightSize):
        super().__init__()
        self.timer = QTimer(self)
        self.timer.setInterval(3000)
        self.timer.timeout.connect(self.show_animation)
        self.load_finish_singal.connect(self.timer.start)
        self.e = MyTools()
        self.param_init()
        self.widthSize = widthSize
        self.heightSize = heightSize
        self.load_recommends(recommends, type)

    def param_init(self):
        self.__recommend_list = []
        self.button_list = []
        self.__record_list = []
        self.current_index = 0
        self.__firstFlag = True

    def load_recommends(self, recommends, type):
        """
        加载轮播图片以及文字
        :return:
        """
        if recommends:
            self.__recommend_list = recommends
            main_layout = QVBoxLayout()
            self.customer_label = ClickQLabel()
            self.customer_label.setFixedHeight(self.heightSize)
            # self.customer_label.setFixedSize(self.widthSize, self.heightSize)
            self.customer_label.hovered.connect(lambda s: self.controlBtnVisibled(s))
            self.customer_label.clicked.connect(
                lambda: self.ratationClicked_signal.emit(self.__record_list[self.current_index]))
            self.customer_label.clicked.connect(lambda: print(self.__record_list[self.current_index]))

            upLayout = QHBoxLayout(self.customer_label)
            upLayout.setContentsMargins(0, 0, 0, 0)
            upLayout.setSpacing(0)

            self.leftBtn = QPushButton("<")
            self.leftBtn.setToolTip("上一个")
            self.leftBtn.setObjectName("leftBtn")
            self.leftBtn.clicked.connect(lambda: self.changePicByControlBtn("pre"))
            upLayout.addWidget(self.leftBtn)
            upLayout.setAlignment(self.leftBtn, Qt.AlignLeft | Qt.AlignCenter)

            self.rightBtn = QPushButton(">")
            self.rightBtn.setToolTip("下一个")
            self.rightBtn.setObjectName("rightBtn")
            self.rightBtn.clicked.connect(lambda: self.changePicByControlBtn("next"))
            # self.setStyleSheet("""#leftBtn,#rightBtn{border-radius:20px;border:3px solid rgb(255, 85, 127);color:rgb(85, 170, 255);width:40;height:40;font: 175 10pt "Arial";}#leftBtn:hover,#rightBtn:hover{color:rgb(255,156,0);background-color:rgba(255,156,0,0.4)}""")
            self.setStyleSheet("""#leftBtn{border-radius: 0 70px 70px 0;
    border-top-left-radius: 0px;
    border-top-right-radius: 35px;
	cursor: pointer;
    border-bottom-right-radius: 35px;
    border-bottom-left-radius: 0px;
width:70;
height:70;
font: 175 10pt "Arial";
background-color:rgba(144,144,144,0.5)}

#rightBtn{border-radius: 70px 0 0 70px;
    border-top-left-radius: 35px;
    border-top-right-radius: 0px;
    border-bottom-right-radius: 0px;
    border-bottom-left-radius: 35px;
width:70;
height:70;
font: 175 10pt "Arial";
background-color:rgba(144,144,144,0.5)}

#leftBtn:hover,#rightBtn:hover{
cursor: pointer;
border-radius: 0 70px 70px 0;
    border-top-left-radius: 0px;
    border-top-right-radius: 35px;
    border-bottom-right-radius: 35px;
    border-bottom-left-radius: 0px;
width:70;
height:70;
background-color:rgba(255,99,14,0.7)}
#rightBtn:hover{
cursor: pointer;
border-radius: 70px 0 0 70px;
    border-top-left-radius: 35px;
    border-top-right-radius: 0px;
    border-bottom-right-radius: 0px;
    border-bottom-left-radius: 35px;
width:70;
height:70;
background-color:rgba(255,99,14,0.7)}
""")
            upLayout.addWidget(self.rightBtn)
            upLayout.setAlignment(self.rightBtn, Qt.AlignRight | Qt.AlignCenter)
            self.leftBtn.hide()
            self.rightBtn.hide()

            self.bottom_layout = QHBoxLayout()
            top_h_layout = QHBoxLayout()
            spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
            spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
            self.bottom_layout.addItem(spacerItem1)
            coor = self.customer_label.mapToGlobal(QPoint(0, 0))
            button_list = []
            for i, d in enumerate(recommends):
                if type == "activityRecommend":
                    name = d.get("sTitle")
                    intro = self.e.clean_txt(d['sDigest'])
                    self.__record_list.append(str(d.get("tProfile").get("lProfileRoom")))
                elif type == "cateRecommend":
                    name = ""
                    intro = ""
                    anchorUrl = d.get("sActionUrl")
                    self.__record_list.append(anchorUrl)
                exec('btn_{}=CPushButton()'.format(i))
                exec('btn_{}.hovered.connect(lambda:self.change_pic("{}"))'.format(i, i), locals())
                exec(
                    'btn_%s.setStyleSheet("""QPushButton{border:1px solid rgb(167, 167, 167);padding-left:20;padding-right:20;padding-bottom:20;padding-top:20;}QPushButton::hover{background-color:rgb(85,170,255);}QPushButton:pressed{background-color: rgb(85, 170, 255);}QPushButton:checked{background-color: rgb(85, 170, 255);}""")' % str(
                        i))
                exec('btn_{}.setToolTip("""{}""")'.format(i, intro))
                exec("btn_{}.setFixedSize(20,5)".format(i))
                exec("btn_{}.setCheckable(True)".format(i))
                exec("btn_{}.setAutoExclusive(True)".format(i))
                exec('self.bottom_layout.addWidget(btn_{})'.format(i))
                exec('button_list.append(btn_{})'.format(i))
            self.button_list = button_list
            self.bottom_layout.addItem(spacerItem2)
            top_h_layout.addWidget(self.customer_label)
            main_layout.addLayout(top_h_layout)
            main_layout.addLayout(self.bottom_layout)
            self.setLayout(main_layout)
            self.load_pic_bytes(type)
            self.load_finish_singal.emit()

    def load_pic_bytes(self, type):
        """
        加载轮播图到本地
        :return:
        """
        self.pic_bytes_list = []
        for i in self.__recommend_list:
            if type == "activityRecommend":
                bytes = self.e.do_get_img_bytes(i['sPicUrl'])
            elif type == "cateRecommend":
                bytes = self.e.do_get_img_bytes(i['sPicUrl'])
            self.pic_bytes_list.append(bytes)

    def show_animation(self):
        """
        展示轮播图
        :return:
        """
        self.set_pic(self.current_index)
        if self.current_index + 1 == len(self.__recommend_list):
            self.current_index = 0
        else:
            self.current_index += 1
        print(self.current_index)

    def set_pic(self, index):
        """
        改变当前图片
        :param index:
        :return:
        """
        pic_bytes = self.pic_bytes_list[int(index)]
        pix = QPixmap()
        pix.loadFromData(pic_bytes)
        self.customer_label.setPixmap(pix)
        btn = self.button_list[int(index)]
        btn.setChecked(True)
        self.customer_label.setToolTip(btn.toolTip())  # 修改toolTip

    def change_pic(self, index):
        """
        按钮被单击,改变当前显示轮播图
        :return:
        """
        self.set_pic(index)
        self.current_index = int(index)

    def changePicByControlBtn(self, direction):
        """
        :param direction:
        :return:
        """
        maxNum = len(self.__recommend_list)
        index = self.current_index
        if direction == "pre":
            if index - 1 < 0:
                index = maxNum - 1
            else:
                if self.__firstFlag:
                    index -= 2
                else:
                    index -= 1
        elif direction == "next":
            if index + 1 >= maxNum:
                index = 0
            else:
                if self.__firstFlag:
                    index = index
                else:
                    index += 1
        self.__firstFlag = False
        self.change_pic(index)

    pyqtSlot(bool)
    def controlBtnVisibled(self, flag):
        """
        显示、隐藏左右button
        :param flag:
        :return:
        """
        self.leftBtn.setVisible(flag)
        self.rightBtn.setVisible(flag)
        if flag:
            self.timer.stop()
        else:
            self.timer.start()


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)
    data = HuyaSpider().getRecommendBanner()
    print(data)
    w = CRotaion_widget("activityRecommend", data, 900, 180)
    w.show()
    sys.exit(app.exec_())

2.engine.py

轮播图数据获取引擎

import json
import re
import requests


class MyTools(object):
    def do_get_img_bytes(self, url):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
        }
        try:
            r = requests.get(url, headers=headers)
            if r.status_code == 200:
                return r.content
            else:
                return False
        except:
            return False

    def clean_txt(self, str):
        rstr = r"[\/\\\:\*\?\"\<\>\()|'“”r\n\u200b]"
        str = re.sub(rstr, "_", str)
        return str


class HuyaSpider(object):
    def __init__(self):
        self.u = MyTools()
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
        }

    def do_request(self, url, headers, flag=False):
        """
        访问url拿到网页源代码
        :param url:
        :return:
        """
        try:
            r = requests.get(url, headers=headers)
            if r.status_code == 200:
                if flag:
                    html = r.text.encode().decode("unicode-escape")
                else:
                    html = r.text
                return html
            else:
                return False
        except requests.exceptions:
            return False

    def getRecommendBanner(self):
        """
        获取主界面推荐轮播图
        :return:
        """

        api = "https://live.cdn.huya.com/liveHttpUI/getHomeUpcomingRecommend?ePlatform=1"
        html = self.do_request(api, headers=self.headers)
        if html:
            return json.loads(html).get("vUpcoming")  # 只返回轮播图数据
        else:
            return False

3.CWidgets.py

包含两个自定义的Widget

import sys

from PyQt5.QtCore import Qt, pyqtSignal, QEvent
from PyQt5.QtGui import QMouseEvent, QPainter, QTextOption
from PyQt5.QtWidgets import QPushButton, QLabel, QWidget, QVBoxLayout, QHBoxLayout, QToolButton, QSpacerItem, \
    QSizePolicy
from qtpy import QtCore, QtGui


class CPushButton(QPushButton):
    """
    鼠标放置后发出hover信号
    """
    hovered = pyqtSignal()

    def __init__(self, number=None):
        super().__init__()
        self.setCheckable(True)
        self.setAutoExclusive(True)
        if number == None:
            return
        if number == 0:
            self.setStyleSheet("""QPushButton{height:20px;
width:20px;
border:1px solid rgb(139, 139, 139);
border-radius:10px;
background:rgba(139, 139, 139,0.7)}
QPushButton:hover{
border:1px solid rgb(250, 148, 7);
background:rgb(250, 148, 7);
border-radius:10px;
}
QPushButton:checked{
border:1px solid rgb(250, 148, 7);
background:rgb(250, 148, 7);
border-radius:10px;
}
QPushButton:unchecked{height:20px;
width:20px;
border:1px solid rgb(139, 139, 139);
border-radius:10px;
background:rgba(139, 139, 139,0.7)}""")
        elif number == 1:
            self.setStyleSheet("""QPushButton{height:4px;
width:4px;
border:1px solid rgb(139, 139, 139);
border-radius:2px;
background:rgba(139, 139, 139,0.7)}
QPushButton:hover{
border:1px solid rgb(194, 12, 12);
background:rgb(194, 12, 12);
border-radius:2px;
}
QPushButton:checked{
border:1px solid rgb(194, 12, 12);
background:rgba(194, 12, 12,0.7);
border-radius:2px;
}
QPushButton:unchecked{height:2px;
width:4px;
border:1px solid rgb(139, 139, 139);
border-radius:2px;
background:rgba(194, 12, 12,0.7)}""")
        elif number == 2:
            self.setStyleSheet("""QPushButton{
    list-style: none;
    float: left;
    width: 164px;
    height: 40px;
    border:none;
    background-color: #e3e2e2;
    font-size: 14px;
    text-align: center;
    line-height: 40px;
    color: #424242;
    letter-spacing: 1px;
}
QPushButton:hover{
color:rgb(203, 167, 114);
background-color:#f7f6f6;
border:0px solid black;
border-bottom: 2px solid #cea861;
}
QPushButton:checked{
color:rgb(203, 167, 114);
background-color:#f7f6f6;
border:0px solid black;
border-bottom: 2px solid #cea861;
}""")

    def enterEvent(self, a0: QtCore.QEvent):
        self.hovered.emit()
        super(CPushButton, self).enterEvent(a0)


class ClickQLabel(QLabel):
    """
    可以点击、鼠标进入、退出
    自动发射信号
    """
    clicked = pyqtSignal()  # 点击信号
    hovered = pyqtSignal(bool)

    def __init__(self, parent=None, ):
        super(ClickQLabel, self).__init__(parent)
        self.setObjectName('clickQLabel')
        self.setScaledContents(True)  # 图片标签自适应

    def mousePressEvent(self, ev: QMouseEvent):
        self.clicked.emit()

    def enterEvent(self, a0: QEvent):
        # 改变鼠标手势
        self.setCursor(Qt.PointingHandCursor)
        self.hovered.emit(True)

    def leaveEvent(self, a0: QtCore.QEvent):
        self.hovered.emit(False)


四.下载地址

前三个轮播图获取可以去这篇文章自取

1.QQ飞车

https://wwt.lanzoul.com/i84Ry05saref

2.英雄联盟

https://wwt.lanzoul.com/iCRhV05s8iyj

3.英雄联盟Pro

https://wwt.lanzoul.com/i3x9i05v0lsb

4.网易云音乐

https://wwt.lanzoul.com/iHAFK05s8nch

5.腾讯视频

https://wwt.lanzoul.com/iZHKo05s8a1i

五.总结

本次展示了几个使用PyQt5开发的轮播图,重点在于如何美观地展示图片数据,上面的示例中,前三个的数据都是通过网络获取地,后面三个的数据是在本地读取的。思路、代码方面有什么不足欢迎各位大佬指正、批评!觉得还行,能点个赞吗?
请添加图片描述

posted on 2022-07-04 12:55  懷淰メ  阅读(299)  评论(0编辑  收藏  举报