- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 QListWidget
,它由 QLabel
通过 .setItemWidget()
和拖放模式 InternalMove
填充code>,当我在列表中移动项目时,其标签就会消失。
如何解决这个问题?
重现的最小示例
from PyQt5.QtWidgets import (
QApplication, QLabel, QStyle,
QListWidget, QListWidgetItem
)
from PyQt5.QtCore import QSize
import sys
if __name__ == '__main__':
app = QApplication(sys.argv)
list = QListWidget()
list.setFixedHeight(400)
list.setDragDropMode(QListWidget.DragDropMode.InternalMove)
for _ in range(8):
item = QListWidgetItem()
item.setSizeHint(QSize(40, 40))
list.addItem(item)
label = QLabel()
label.setPixmap(list.style().standardIcon(
QStyle.StandardPixmap.SP_ArrowUp).pixmap(QSize(40,40)))
list.setItemWidget(item, label)
list.show()
sys.exit(app.exec())
编辑
阅读 .setItemWidget()
的文档后,其中指出:
This function should only be used to display static content in the place of a list widget item. If you want to display custom dynamic content or implement a custom editor widget, use QListView and subclass QStyledItemDelegate instead.
我想知道这是否与该问题有关,以及在这种情况下“静态内容”意味着什么,QLabel
是否被视为“动态内容”?
编辑#2
问题出在 dropEvent()
内部,调用 dropMimeData()
进而创建一个完整的新项目? (rowsInserted
被调用),我猜这不应该发生在 self 项目上,因为拖动项目中设置的小部件没有序列化并存储在 mimedata
中,所以该小部件是解耦的,当您从不同的列表中拖放项目时,通常会调用 dropMimeData()
。
所以我想解决这个问题的一个丑陋的方法是通过QMimeData将手动序列化的小部件存储在
并在放入 QListWidget.mimeData()
中作为自定义mimetype
。 setData()QListWidget.dropMimeData()
后重新创建小部件。
例如:
from PyQt5.QtWidgets import (
QApplication, QLabel, QStyle,
QListWidget, QListWidgetItem
)
from PyQt5.QtCore import QSize, QMimeData, QBuffer, QIODevice
from PyQt5.QtGui import QPixmap
import pickle
import sys
class ListWidget(QListWidget):
def mimeData(self, items:list[QListWidgetItem]) -> QMimeData:
mimedata = QListWidget.mimeData(self, items)
# e.g. serialize pixmap
custommime = []
for item in items:
label:QLabel = self.itemWidget(item)
buff = QBuffer()
buff.open(QIODevice.OpenModeFlag.WriteOnly)
label.pixmap().save(buff, 'PNG')
buff.close()
custommime.append(buff.data())
mimedata.setData('application/custommime', pickle.dumps(custommime))
#
return mimedata
def dropMimeData(self, index:int, mimedata:QMimeData, action) -> bool:
result = QListWidget.dropMimeData(self, index, mimedata, action)
# e.g. recreate pixmap
if mimedata.hasFormat('application/custommime'):
for i, data in enumerate(
pickle.loads(mimedata.data('application/custommime')),
start=index):
pixmap = QPixmap()
pixmap.loadFromData(data, 'PNG')
label = QLabel()
label.setPixmap(pixmap)
self.setItemWidget(self.item(i), label)
#
return result
if __name__ == '__main__':
app = QApplication(sys.argv)
list = ListWidget()
list.setFixedHeight(400)
list.setDragDropMode(QListWidget.DragDropMode.InternalMove)
list.setSelectionMode(QListWidget.SelectionMode.ExtendedSelection)
for i in range(8):
item = QListWidgetItem()
item.setSizeHint(QSize(40, 40))
list.addItem(item)
label = QLabel()
label.setPixmap(list.style().standardIcon(
QStyle.StandardPixmap.SP_DialogOkButton + i).pixmap(QSize(40,40)))
list.setItemWidget(item, label)
list.show()
sys.exit(app.exec())
最佳答案
更新
该错误现已在最新版本的 Qt5 和 Qt6 中修复。
这是由 Qt 错误引起的,该错误仅影响最近的版本。当使用 Qt-5.15.6 和 Qt-6.4.0 时,我可以一致地重现它 - 但不能,例如Qt-5.12.1。该问题似乎与 QTBUG-100128 密切相关.
PyQt5/6 的解决方法(基于 solution by PaddleStroke )如下:
class ListWidget(QListWidget):
def dragMoveEvent(self, event):
if ((target := self.row(self.itemAt(event.pos()))) ==
(current := self.currentRow()) + 1 or
(current == self.count() - 1 and target == -1)):
event.ignore()
else:
super().dragMoveEvent(event)
旧答案:
不幸的是,经过今天的一些进一步实验,下面给出的建议解决方法似乎并不是一个有效的解决方案。我发现还可以通过拖放到非空区域来使项目小部件消失。
在测试了 Qt5 的其他版本后,我可以确认该错误在 5.12.x、5.13.x、5.14.x、5.15.0 和 5.15.1 中完全不存在。这与上面现有的 Qt 错误报告一致,该报告将 Qt-5.15.2 确定为引入该错误的版本。
与问题中建议的相反,没有任何理由不应该将标签用作项目小部件。术语“静态内容”,仅表示“不由用户定义的自定义绘图更新”。
这个错误似乎是 QTBUG-87057 的回归,这对拖放过程中 ListView 行的移动方式进行了大量内部更改。这些变化的复杂性可能意味着消除其负面影响的简单解决方法是不可能的。这些更改影响所有高于 5.15.1 的 Qt5 版本和高于 6.0 的 Qt6 版本。
class ListWidget(QListWidget):
def dropEvent(self, event):
if (self.currentRow() < self.count() - 1 or
self.itemAt(event.pos()) is not None):
super().dropEvent(event)
list = ListWidget()
...
或使用事件过滤器:
class Monitor(QObject):
def eventFilter(self, source, event):
if event.type() == QEvent.Drop:
view = source.parent()
if (view.currentRow() == view.count() - 1 and
view.itemAt(event.pos()) is None):
return True
return super().eventFilter(source, event)
monitor = Monitor()
list = QListWidget()
list.viewport().installEventFilter(monitor)
...
关于python-3.x - QListWidgetItem 内的小部件在内部移动后消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74263946/
我正在尝试使用 QListWidgetItems 制作 QListWidget。 我希望 QListWidgetItems 具有边框和背景,例如绿。 所选项目应该有另一个背景,例如红色的。 我试图用样
我有一个非常简单的QListWidget对象,我想构建一个文件夹列表。当我将一个项目添加到我的列表中时,我会执行以下操作: void LessCC::on_addFolderButton_clicke
我已经定义了一个小部件,它包含一个 QLabel(和其他元素),它应该显示换行的文本。这个 QLabel 有: 横向策略:最小值 垂直策略:MinimumExpanding 自动换行:真 小部件有:
我有一个 QDialog,我用它从 SQL 表中显示的项目列表中进行选择。选择项目后,我需要返回表并读取所选项目的所有数据。我想将 SQL ID 添加到 WidgetItem。 我创建了一个继承自 Q
我在表单中有一个 QListWidget,其中的 QListWidgetItem 显示“添加新的”。当我点击它时,我希望发生一系列事情: QInputDialog::getText 请求新项目的内容。
我正在尝试将 QlistWidgetItem 设置为使用 in 存储对象。我正在使用 setData 函数来实现此目的。我可以将数据存储在列表 A 中的项目中。但是我试图将 QlistWidgetIt
我有一个 QListWidgetItem,它有一个 QWidget 和一些 QLabels。标签(imageLabel、titleLabel 和 descriptionLabel)的高度因文本长度而异
我现在真的卡住了..我的应用程序可以通过单击创建(动画)帧,可以移动、删除或编辑这些帧。我想要某种右键单击上下文菜单来删除它们。 我现在的尝试是创建一个 QListWidget,并在其中插入 QLis
我正在开发我的第一个 QT 应用程序,但我遇到了 QListWidgetItems 的问题。 我会有不同类型的列表。对于复选框列表,使用: listElement[i]->setFlags(Qt::I
我有一个 QListWidget,它在 iconMode 中用作 viewMode。当我为 QListWidgetItem 设置 QIcon 和文本时,图标显示在文本的顶部。如果我在 listMode
我做了一个 QListWidget .在 QLisitWidgetItems , 我加了一个 QVBoxLayout .那个QVBoxLayout包含三个 QLabels .如何获取里面的值 QLab
我偶然发现了这个(显然,这是一个更大的应用程序的摘录): import sys from PySide2.QtCore import * from PySide2.QtGui import * fro
所以基本上我刚刚开始学习 PyQt,我想在 listWidget 中获取元素的文本,但每次我尝试 self.listWidget.currentItem().text() 时都会抛出错误。为什么? i
我正在编写一种搜索算法,用于搜索 QListWidget 并根据用户在搜索栏中键入的内容返回相关匹配项。我希望所有匹配项都以淡黄色突出显示。 例如: 如果用户在搜索栏中键入“ilt”,我想用文本“Wr
下面的代码创建了一个 QListWidget,并为 QListWidgetItem 分配了缩略图。 如果您展示如何在 QListWidgetItem 周围制作彩色边框,我将不胜感激 这是显示概念的 P
如果我们使用 QListWidgetItem 引用进行操作,我们如何更改文本的大小?任何帮助将不胜感激。 最佳答案 试试这个,使用 QListWidgetItem::font() 方法获取项目的当前字
我有一个 QListWidgetItem* 并且想知道是否可以从这个指针中提取行而不遍历整个列表 最佳答案 如果需要行号,请使用下面的函数: int QListWidget::row(const QL
我有一个带有 QListWidget 的表单,我在其中反复添加新项目。一切都完美无瑕,除了一件事:无论我传递给它们什么标志,这些项目都是三态的。因此,必须单击该项目两次才能选中/取消选中它们。我该怎么
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我有一个 QListWidget的日历。每个QListWidgetItem在逻辑上与 Calendar 的实例相关联,这是一个属于应用程序模型端的类。 我可以使用 QListWidgetItem::s
我是一名优秀的程序员,十分优秀!