在python2和PySide2环境下可以直接运行(除了resource是资源文件(不提供),只是加载了一个图标给Item对象)
VerticalWheelThread只是在滚动滚轮的时候用了一个Qthread实现滚动动画效果
ListWidget对象在初始化的时候重新指定滑块为自定义的滑块对象ScrollBar
ScrollBar的valueChanged信号更新max_page从而使ListWidget实现动态添加Item
#!/usr/bin/env python27
# -*- coding: utf-8 -*-
import time
import math
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
import resource
class VerticalWheelThread(QThread):
delta_val = Signal(int)
def __init__(self, parent):
super(VerticalWheelThread, self).__init__()
self.delta = 0
self.direct = 1
self.delta_val.connect(parent.set_value)
def set_delta(self, delta):
self.delta = delta
self.direct = 1 if self.delta > 0 else -1
def run(self):
# 每1毫秒移动一个像素,实现滚轮动画效果
for i in range(abs(self.delta)):
time.sleep(0.001)
self.delta_val.emit(self.direct)
class ScrollBar(QScrollBar):
def __init__(self, parent):
super(ScrollBar, self).__init__(parent)
self.parent_wid = parent
self.max_page = 0
self.current_page = 1
self.document_length = 0
self.wheel_thread = VerticalWheelThread(self)
self.valueChanged.connect(self.value_changed)
def gridSize(self):
return self.parent_wid.gridSize()
def gridWidth(self):
return self.gridSize().width()
def gridHeight(self):
return self.gridSize().height()
def rowCount(self):
return self.parent_wid.rowCount()
def colCount(self):
return self.parent_wid.colCount()
def itemCount(self):
return self.parent_wid.count()
def rectAreaHeight(self):
return self.parent_wid.rect().height()
def rectAreaWidth(self):
return self.parent_wid.rect().width()
def documentRowCount(self):
_height = self.rectAreaHeight() + self.document_length
return int(math.ceil(float(_height) / float(self.gridHeight())))
def update_page(self):
_count = self.rowCount() * self.colCount()
_item_count = self.itemCount()
if _item_count == 0:
self.max_page = 0
elif _item_count <= _count:
self.max_page = 1
else:
self.max_page = _item_count/_count + 1 if (_item_count % _count) else _item_count/_count
self.current_page = int(math.ceil(float(self.documentRowCount()) / float(self.rowCount())))
if self.current_page == self.max_page or self.document_length == self.maximum():
self.parent_wid.update_list(self.max_page+1)
def value_changed(self, value):
self.document_length = value
self.update_page()
def set_value(self, value):
val = max(0, self.value() - value)
self.setValue(val)
def wheelEvent(self, event):
delta = event.delta()
self.wheel_thread.set_delta(delta)
self.wheel_thread.start()
class ListWidget(QListWidget):
def __init__(self, parent):
super(ListWidget, self).__init__(parent)
self.assets_data = [str(x).zfill(4) for x in range(100000)]
self.initUi()
def initUi(self):
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
scroll_bar = ScrollBar(self)
self.setVerticalScrollBar(scroll_bar)
self.setViewMode(QListWidget.IconMode)
self.setIconSize(QSize(192, 108))
self.setContentsMargins(0, 0, 0, 0)
self.setGridSize(QSize(200, 138))
self.setResizeMode(self.Adjust)
self.setFlow(self.LeftToRight)
def init_list(self):
row = int(math.floor(float(self.parent().width()) / float(self.gridSize().width())))
col = int(math.floor(float(self.parent().height()) / float(self.gridSize().height())))
for i in range(min(2 * row * col, len(self.assets_data))):
self.addItem(Item(self.assets_data[i]))
def update_list(self, page):
_count = self.rowCount() * self.colCount()
items_count = self.count()
for i in range(min(_count * page, len(self.assets_data))):
if i < items_count:
continue
self.addItem(Item(self.assets_data[i]))
def colCount(self):
rect_width = self.rect().width()
grid_width = self.gridSize().width()
return int(math.floor(float(rect_width) / float(grid_width)))
def rowCount(self):
rect_height = self.rect().height()
grid_height = self.gridSize().height()
return int(math.ceil(float(rect_height) / float(grid_height)))
def resizeEvent(self, event):
super(ListWidget, self).resizeEvent(event)
class Item(QListWidgetItem):
def __init__(self, text):
super(Item, self).__init__()
self.setIcon(QIcon(':/resources/folder.png'))
self.setText(text)
self.setSizeHint(QSize(192, 130))
self.setTextAlignment(Qt.AlignBottom | Qt.AlignHCenter)
class Dlg(QDialog):
def __init__(self, parent=None):
super(Dlg, self).__init__(parent)
self.resize(1280, 720)
self.move(500, 200)
layout1 = QVBoxLayout(self)
layout1.setContentsMargins(0, 0, 0, 0)
layout1.setSpacing(0)
self.list_widget = ListWidget(self)
layout1.addWidget(self.list_widget)
self.list_widget.init_list()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ui = Dlg()
ui.show()
sys.exit(app.exec_())