@
目录本次将之前做的和新做的轮播图Demo进行展示。废话不多说,直接上图
数据源:网络
格式:接口Json
参考网站:http://www.kuwo.cn/
支持自动、手动切换,导航栏切换图片
数据源:网络
格式:接口Json
参考网站:数据来源QQ飞车客户端抓包
官网:http://speed.qq.com/main.shtml
支持自动、手动切换,导航栏切换图片(右上角那个不规则按钮还不能实现)
数据源:网络
格式:接口Json
参考网站:https://www.huya.com/
支持自动、手动切换,导航栏、左右按钮切换图片
数据源:本地
格式:列表
参考网站:https://music.163.com/
支持自动、手动切换,导航栏、左右按钮切换图片,轮播图切换动画为淡出
数据源:本地
格式:列表
参考网站:https://lol.qq.com/main.shtml
支持自动、手动切换,导航栏切换图片,轮播图切换动画为正弦缓入
在上一个的基础上进行改进,重写QStackWidget的SetCurrentInex()函数,实现了过渡动画的显示
数据源:本地
格式:列表
参考网站:https://v.qq.com/
这个上了点难度,不过只要慢慢拆解,还是不难的。
支持自动、手动切换,导航栏切换图片,支持手动切换推荐视频
值得一提的是,“猜你会追”页面有个子页面,里面是一些电影、电视剧推荐,要通过按钮手动切换推荐,鼠标放在推荐上,封面会自动放大(注意“下一张”按钮位置)。
动图被压缩了,可能看不太清,贴一张静图。
贴一下demo3的代码
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_())
轮播图数据获取引擎
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
包含两个自定义的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)
前三个轮播图获取可以去这篇文章自取
https://wwt.lanzoul.com/i84Ry05saref
https://wwt.lanzoul.com/iCRhV05s8iyj
https://wwt.lanzoul.com/i3x9i05v0lsb
https://wwt.lanzoul.com/iHAFK05s8nch
https://wwt.lanzoul.com/iZHKo05s8a1i
本次展示了几个使用PyQt5开发的轮播图,重点在于如何美观地展示图片数据,上面的示例中,前三个的数据都是通过网络获取地,后面三个的数据是在本地读取的。思路、代码方面有什么不足欢迎各位大佬指正、批评!觉得还行,能点个赞吗?