删除自定义Item

This commit is contained in:
Irony 2018-11-04 18:09:42 +08:00
parent badbbac675
commit c092046a9d
5 changed files with 109 additions and 84 deletions

View file

@ -24,6 +24,7 @@ encoding//\u5176\u5B83/\u81EA\u5B9A\u4E49import/src/test.py=utf-8
encoding//\u5176\u5B83/\u81EA\u5B9A\u4E49\u5C5E\u6027\u6D4B\u8BD5/\u81EA\u5B9A\u4E49\u5C5E\u6027\u6D4B\u8BD5.py=utf-8
encoding//\u5217\u8868/QListView/\u663E\u793A\u81EA\u5B9A\u4E49Widget.py=utf-8
encoding//\u5217\u8868/QListView/\u663E\u793A\u81EA\u5B9A\u4E49Widget\u5E76\u6392\u5E8F.py=utf-8
encoding//\u5217\u8868/QListWidget/\u5220\u9664\u81EA\u5B9A\u4E49Item.py=utf-8
encoding//\u5217\u8868/QListWidget/\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay.py=utf-8
encoding//\u5217\u8868/QListWidget/\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay_Flow.py=utf-8
encoding//\u5217\u8868/QListWidget/\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay_ListWidget.py=utf-8

View file

@ -1,83 +0,0 @@
# QListWidget 拖拽、框选
```python
# 隐藏横向滚动条
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# 不能编辑
self.setEditTriggers(self.NoEditTriggers)
# 开启拖功能
self.setDragEnabled(True)
# 只能往外拖
self.setDragDropMode(self.DragOnly)
# 忽略放
self.setDefaultDropAction(Qt.IgnoreAction)
# ****重要的一句作用是可以单选多选。Ctrl、Shift多选可从空白位置框选****
# ****不能用ExtendedSelection,因为它可以在选中item后继续框选会和拖拽冲突****
self.setSelectionMode(self.ContiguousSelection)
# 设置从左到右、自动换行、依次排列
self.setFlow(self.LeftToRight)
self.setWrapping(True)
self.setResizeMode(self.Adjust)
# item的间隔
self.setSpacing(5)
# 橡皮筋(用于框选效果)
self._rubberPos = None
self._rubberBand = QRubberBand(QRubberBand.Rectangle, self)
```
## 拖动Item
```python
# 实现拖拽的时候预览效果图
# 这里演示拼接所有的item截图(也可以自己写算法实现堆叠效果)
def startDrag(self, supportedActions):
items = self.selectedItems()
drag = QDrag(self)
mimeData = self.mimeData(items)
# 由于QMimeData只能设置image、urls、str、bytes等等不方便
# 这里添加一个额外的属性直接把item放进去,后面可以根据item取出数据
mimeData.setProperty('myItems', items)
drag.setMimeData(mimeData)
pixmap = QPixmap(self.viewport().visibleRegion().boundingRect().size())
pixmap.fill(Qt.transparent)
painter = QPainter()
painter.begin(pixmap)
for item in items:
rect = self.visualRect(self.indexFromItem(item))
painter.drawPixmap(rect, self.viewport().grab(rect))
painter.end()
drag.setPixmap(pixmap)
drag.setHotSpot(self.viewport().mapFromGlobal(QCursor.pos()))
drag.exec_(supportedActions)
```
## 模拟框选
```python
def mousePressEvent(self, event):
# 列表框点击事件,用于设置框选工具的开始位置
super(DragListWidget, self).mousePressEvent(event)
if event.buttons() != Qt.LeftButton or self.itemAt(event.pos()):
return
self._rubberPos = event.pos()
self._rubberBand.setGeometry(QRect(self._rubberPos, QSize()))
self._rubberBand.show()
def mouseReleaseEvent(self, event):
# 列表框点击释放事件,用于隐藏框选工具
super(DragListWidget, self).mouseReleaseEvent(event)
self._rubberPos = None
self._rubberBand.hide()
def mouseMoveEvent(self, event):
# 列表框鼠标移动事件,用于设置框选工具的矩形范围
super(DragListWidget, self).mouseMoveEvent(event)
if self._rubberPos:
pos = event.pos()
lx, ly = self._rubberPos.x(), self._rubberPos.y()
rx, ry = pos.x(), pos.y()
size = QSize(abs(rx - lx), abs(ry - ly))
self._rubberBand.setGeometry(
QRect(QPoint(min(lx, rx), min(ly, ry)), size))
```
## 截图
![截图](ScreenShot/1.gif)

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View file

@ -0,0 +1,99 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2018年11月4日
@author: Irony
@site: https://pyqt5.com, https://github.com/892768447
@email: 892768447@qq.com
@file: 删除Item
@description:
"""
from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLineEdit, QPushButton,\
QListWidgetItem, QVBoxLayout, QListWidget
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
class ItemWidget(QWidget):
itemDeleted = pyqtSignal(QListWidgetItem)
def __init__(self, text, item, *args, **kwargs):
super(ItemWidget, self).__init__(*args, **kwargs)
self._item = item # 保留list item的对象引用
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(QLineEdit(text, self))
layout.addWidget(QPushButton('x', self, clicked=self.doDeleteItem))
def doDeleteItem(self):
self.itemDeleted.emit(self._item)
def sizeHint(self):
# 决定item的高度
return QSize(200, 40)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
# 列表
self.listWidget = QListWidget(self)
layout.addWidget(self.listWidget)
# 清空按钮
self.clearBtn = QPushButton('清空', self, clicked=self.doClearItem)
layout.addWidget(self.clearBtn)
# 添加测试数据
self.testData()
def doDeleteItem(self, item):
# 根据item得到它对应的行数
row = self.listWidget.indexFromItem(item).row()
# 删除item
item = self.listWidget.takeItem(row)
# 删除widget
self.listWidget.removeItemWidget(item)
del item
def doClearItem(self):
# 清空所有Item
for _ in range(self.listWidget.count()):
# 删除item
# 一直是0的原因是一直从第一行删,删掉第一行后第二行变成了第一行
# 这个和删除list [] 里的数据是一个道理
item = self.listWidget.takeItem(0)
# 删除widget
self.listWidget.removeItemWidget(item)
del item
def testData(self):
# 生成测试数据
for i in range(100):
item = QListWidgetItem(self.listWidget)
widget = ItemWidget('item: {}'.format(i), item, self.listWidget)
# 绑定删除信号
widget.itemDeleted.connect(self.doDeleteItem)
self.listWidget.setItemWidget(item, widget)
if __name__ == '__main__':
import sys
import cgitb
sys.excepthook = cgitb.enable(1, None, 5, 'text')
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

View file

@ -24,4 +24,12 @@
1. 使用`QNetworkAccessManager`进行异步下载数据和图片
2. 滚动条滑动到底部加载更多
![截图](QListWidget/腾讯视频热播列表/ScreenShot/1.gif)
![截图](QListWidget/腾讯视频热播列表/ScreenShot/1.gif)
### 3. [删除自定义Item](QListWidget/删除自定义Item.py)
1. 删除item时先要通过`QListWidget.indexFromItem(item).row()`得到它的行数
2. 通过`takeItem`函数取出该Item并删除掉,`item = self.listWidget.takeItem(row)`
3. 移除item对应的自定义控件`self.listWidget.removeItemWidget(item)`
4. 如果是清空所有Item可以通过循环删除但是删除的时候行号一直是0即可原因和删除list数组一样。
![截图](QListWidget/ScreenShot/删除自定义Item.gif)