class ScrollWindow(QScrollArea): def __init__(self, *args, **kwargs): super(ScrollWindow, self).__init__(*args, **kwargs) # self.setAcceptDrops(True) # 2 self.resize(800, 600) self.setFrameShape(self.NoFrame) self.setWidgetResizable(True) self.setAlignment(Qt.AlignCenter) self._loadStart = False # 网格窗口 self._widget = GridWidget(self) self._widget.loadStarted.connect(self.setLoadStarted) self.setWidget(self._widget) #################################################### # 连接竖着的滚动条滚动事件 # self.verticalScrollBar().actionTriggered.connect(self.onActionTriggered) #################################################### # 进度条 self.loadWidget = QSvgWidget(self, minimumHeight=180, minimumWidth=180, visible=False) self.loadWidget.load(Svg_icon_loading) def setLoadStarted(self, started): self._loadStart = started self.loadWidget.setVisible(started) def onActionTriggered(self, action): # 这里要判断action=QAbstractSlider.SliderMove,可以避免窗口大小改变的问题 # 同时防止多次加载同一个url if action != QAbstractSlider.SliderMove or self._loadStart: return # 使用sliderPosition获取值可以同时满足鼠标滑动和拖动判断 if self.verticalScrollBar().sliderPosition() == self.verticalScrollBar( ).maximum(): # 可以下一页了 self._widget.load() def resizeEvent(self, event): super(ScrollWindow, self).resizeEvent(event) self.loadWidget.setGeometry( int((self.width() - self.loadWidget.minimumWidth()) / 2), int((self.height() - self.loadWidget.minimumHeight()) / 2), self.loadWidget.minimumWidth(), self.loadWidget.minimumHeight())
class Window(QListWidget): Page = 0 def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.resize(800, 600) self.setFrameShape(self.NoFrame) # 无边框 self.setFlow(self.LeftToRight) # 从左到右 self.setWrapping(True) # 这三个组合可以达到和FlowLayout一样的效果 self.setResizeMode(self.Adjust) self._loadStart = False # 连接竖着的滚动条滚动事件 self.verticalScrollBar().actionTriggered.connect( self.onActionTriggered) # 进度条 self.loadWidget = QSvgWidget(self, minimumHeight=120, minimumWidth=120, visible=False) self.loadWidget.load(Svg_icon_loading) # 异步网络下载管理器 self._manager = QNetworkAccessManager(self) self._manager.finished.connect(self.onFinished) def load(self): if self.Page == -1: return self._loadStart = True self.loadWidget.setVisible(True) # 延迟一秒后调用目的在于显示进度条 QTimer.singleShot(1000, self._load) def _load(self): print("load url:", Url.format(self.Page * 30)) url = QUrl(Url.format(self.Page * 30)) self._manager.get(QNetworkRequest(url)) def onFinished(self, reply): # 请求完成后会调用该函数 req = reply.request() # 获取请求 iwidget = req.attribute(QNetworkRequest.User + 1, None) path = req.attribute(QNetworkRequest.User + 2, None) html = reply.readAll().data() reply.deleteLater() del reply if iwidget and path and html: # 这里是图片下载完毕 open(path, "wb").write(html) iwidget.setCover(path) return # 解析网页 self._parseHtml(html) self._loadStart = False self.loadWidget.setVisible(False) def _parseHtml(self, html): # encoding = chardet.detect(html) or {} # html = html.decode(encoding.get("encoding","utf-8")) html = HTML(html) # 查找所有的li list_item lis = html.xpath("//li[@class='list_item']") if not lis: self.Page = -1 # 后面没有页面了 return self.Page += 1 self._makeItem(lis) def _makeItem(self, lis): for li in lis: a = li.find("a") video_url = a.get("href") # 视频播放地址 img = a.find("img") cover_url = "http:" + img.get("r-lazyload") # 封面图片 figure_title = img.get("alt") # 电影名 figure_info = a.find("div/span") figure_info = "" if figure_info is None else figure_info.text # 影片信息 figure_score = "".join(li.xpath(".//em/text()")) # 评分 # 主演 figure_desc = "<span style=\"font-size: 12px;\">主演:</span>" + \ "".join([Actor.format(**dict(fd.items())) for fd in li.xpath(".//div[@class='figure_desc']/a")]) # 播放数 figure_count = ( li.xpath(".//div[@class='figure_count']/span/text()") or [""])[0] path = "cache/{0}.jpg".format( os.path.splitext(os.path.basename(video_url))[0]) cover_path = "Data/pic_v.png" if os.path.isfile(path): cover_path = path iwidget = ItemWidget(cover_path, figure_info, figure_title, figure_score, figure_desc, figure_count, video_url, cover_url, path, self._manager, self) item = QListWidgetItem(self) item.setSizeHint(iwidget.sizeHint()) self.setItemWidget(item, iwidget) def onActionTriggered(self, action): # 这里要判断action=QAbstractSlider.SliderMove,可以避免窗口大小改变的问题 # 同时防止多次加载同一个url if action != QAbstractSlider.SliderMove or self._loadStart: return # 使用sliderPosition获取值可以同时满足鼠标滑动和拖动判断 if self.verticalScrollBar().sliderPosition() == self.verticalScrollBar( ).maximum(): # 可以下一页了 self.load() def resizeEvent(self, event): super(Window, self).resizeEvent(event) self.loadWidget.setGeometry( int((self.width() - self.loadWidget.minimumWidth()) / 2), int((self.height() - self.loadWidget.minimumHeight()) / 2), self.loadWidget.minimumWidth(), self.loadWidget.minimumHeight())