QTableView 如何从单元格中获取纯文本
How to get plain text from a cell QTableView
我正在尝试在两个项目之间进行拖放操作,但无法从我在 table 中单击的单元格中获取信息。我有一个定制 table,它有一个定制模型。
class PyTableWidget(QTableView):
def __init__(self, *args):
super().__init__()
self.setDragEnabled(True)
self.set_stylesheet(*args)
def onLeftClick(self, index):
print('onClick index.row: %s, index.col: %s' % (index.row(), index.column()))
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton:
drag = QDrag(self)
mime = QMimeData()
drag.setMimeData(mime)
drag.exec(Qt.MoveAction)
这是 table 的自定义模型:
class CustomizedNumpyModel(QAbstractTableModel):
def __init__(self, data, parent=None):
QAbstractTableModel.__init__(self, parent)
self._data = np.array(data.values)
self._cols = data.columns
self.r, self.c = np.shape(self._data)
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
value = self._data[index.row(), index.column()]
if isinstance(value, float):
return "%.2f" % value
if isinstance(value, str):
return '%s' % value
return unicode(value)
def rowCount(self, parent=None):
return self.r
def columnCount(self, parent=None):
return self.c
def headerData(self, p_int, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._cols[p_int])
if orientation == Qt.Vertical:
return p_int
return None
def flags(self, index):
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
def setData(self, index, value, role=Qt.EditRole):
index_value = None
based_columns = [6, 8, 10, 12]
if role == Qt.EditRole:
row = index.row()
column = index.column()
tmp = str(value)
if tmp != '':
if column in based_columns:
if column == 6 and tmp in self._cols:
index_no = np.where(self._cols == tmp)[0][0]
self._data[row, column + 1] = self._data[row, index_no]
self._data[row, column] = tmp
elif column in [8, 10, 12]:
for x in range(97, 181):
if self._data[row, x] == int(tmp):
index_value = x
break
col_name = self._cols[index_value]
col_name = col_name.removesuffix('_rank')
self._data[row, column + 1] = col_name
self._data[row, column] = tmp
self.dataChanged.emit(index, index)
return True
else:
return False
这里是接受掉落的另一个小部件中的代码
class PyCustomButton(QPushButton):
def __init__(self, *args):
super().__init__()
self.setCursor(Qt.PointingHandCursor)
self.setAcceptsDrops(True)
self._lista = []
def dragEnterEvent(self, event):
if event.mimeData().hasText():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
self._lista.append(event.mimeData().text())
print(self._lista)
table有以下方面:
Names
First
Second
我想要纯文本,即 First
或 Second
从 table 拖放到自定义按钮中。
简单的解决方案是使用 indexAt()
. Note that it's generally better to start a drag action when the user has moved the mouse by a certain amount of pixels, which defaults to the QApplication startDragDistance()
属性 获取“选定”索引。
class PyTableWidget(QTableView):
_startPos = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
index = self.indexAt(event.pos())
if index.isValid():
self._startPos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton and self._startPos is not None:
delta = (event.pos() - self._startPos).manhattanLength()
if delta >= QApplication.startDragDistance():
drag = QDrag(self)
mime = QMimeData()
mime.setText(self.indexAt(self._startPos).data())
drag.setMimeData(mime)
drag.exec(Qt.MoveAction)
self._startPos = None
return
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self._startPos = None
super().mouseReleaseEvent(event)
请注意,Qt 项目视图已经支持拖放:要在自定义模型中启用该支持,您还需要在 flags()
中添加 Qt.ItemIsDragEnabled
并确保 table 支持通过使用 setDragEnabled(True)
(就像您所做的那样)或通过将视图的 dragDropMode
至少设置为 DragOnly
.
来拖动
唯一剩下的“问题”是从拖动 mime 数据中获取 视图外部的数据,它使用内部格式序列化内容。
虽然这种方法可能看起来更复杂和困难,但如果您打算支持多个项目视图之间的拖放,它也是一个更好的解决方案,因为该序列化格式是所有 Qt 视图的通用和标准格式。
class CustomizedNumpyModel(QAbstractTableModel):
# ...
def flags(self, index):
return (Qt.ItemIsEnabled
| Qt.ItemIsSelectable
| Qt.ItemIsEditable
| Qt.ItemIsDragEnabled)
class PyTableWidget(QTableView):
def __init__(self, *args):
super().__init__(*args)
self.setDragEnabled(True)
# nothing else to implement in this class
class PyCustomButton(QPushButton):
def __init__(self, *args):
super().__init__()
self.setCursor(Qt.PointingHandCursor)
self.setAcceptDrops(True)
self._lista = []
def dragEnterEvent(self, event):
if 'application/x-qabstractitemmodeldatalist' in event.mimeData().formats():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
mimeData = event.mimeData()
if mimeData.hasText():
self._lista.append(mimeData.text())
elif 'application/x-qabstractitemmodeldatalist' in mimeData.formats():
names = []
stream = QDataStream(mimeData.data(
'application/x-qabstractitemmodeldatalist'))
while not stream.atEnd():
# all fields must be read, even if not used
row = stream.readInt()
column = stream.readInt()
for _ in range(stream.readInt()):
role = stream.readInt()
value = stream.readQVariant()
if role == Qt.DisplayRole:
names.append(value)
self._lista.extend(names)
print(self._lista)
注意 setData()
必须 always return 一个 bool。删除最后一个 else:
并将 return False
推回函数的主缩进级别。
我正在尝试在两个项目之间进行拖放操作,但无法从我在 table 中单击的单元格中获取信息。我有一个定制 table,它有一个定制模型。
class PyTableWidget(QTableView):
def __init__(self, *args):
super().__init__()
self.setDragEnabled(True)
self.set_stylesheet(*args)
def onLeftClick(self, index):
print('onClick index.row: %s, index.col: %s' % (index.row(), index.column()))
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton:
drag = QDrag(self)
mime = QMimeData()
drag.setMimeData(mime)
drag.exec(Qt.MoveAction)
这是 table 的自定义模型:
class CustomizedNumpyModel(QAbstractTableModel):
def __init__(self, data, parent=None):
QAbstractTableModel.__init__(self, parent)
self._data = np.array(data.values)
self._cols = data.columns
self.r, self.c = np.shape(self._data)
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
value = self._data[index.row(), index.column()]
if isinstance(value, float):
return "%.2f" % value
if isinstance(value, str):
return '%s' % value
return unicode(value)
def rowCount(self, parent=None):
return self.r
def columnCount(self, parent=None):
return self.c
def headerData(self, p_int, orientation, role):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._cols[p_int])
if orientation == Qt.Vertical:
return p_int
return None
def flags(self, index):
return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable
def setData(self, index, value, role=Qt.EditRole):
index_value = None
based_columns = [6, 8, 10, 12]
if role == Qt.EditRole:
row = index.row()
column = index.column()
tmp = str(value)
if tmp != '':
if column in based_columns:
if column == 6 and tmp in self._cols:
index_no = np.where(self._cols == tmp)[0][0]
self._data[row, column + 1] = self._data[row, index_no]
self._data[row, column] = tmp
elif column in [8, 10, 12]:
for x in range(97, 181):
if self._data[row, x] == int(tmp):
index_value = x
break
col_name = self._cols[index_value]
col_name = col_name.removesuffix('_rank')
self._data[row, column + 1] = col_name
self._data[row, column] = tmp
self.dataChanged.emit(index, index)
return True
else:
return False
这里是接受掉落的另一个小部件中的代码
class PyCustomButton(QPushButton):
def __init__(self, *args):
super().__init__()
self.setCursor(Qt.PointingHandCursor)
self.setAcceptsDrops(True)
self._lista = []
def dragEnterEvent(self, event):
if event.mimeData().hasText():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
self._lista.append(event.mimeData().text())
print(self._lista)
table有以下方面:
Names |
---|
First |
Second |
我想要纯文本,即 First
或 Second
从 table 拖放到自定义按钮中。
简单的解决方案是使用 indexAt()
. Note that it's generally better to start a drag action when the user has moved the mouse by a certain amount of pixels, which defaults to the QApplication startDragDistance()
属性 获取“选定”索引。
class PyTableWidget(QTableView):
_startPos = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
index = self.indexAt(event.pos())
if index.isValid():
self._startPos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton and self._startPos is not None:
delta = (event.pos() - self._startPos).manhattanLength()
if delta >= QApplication.startDragDistance():
drag = QDrag(self)
mime = QMimeData()
mime.setText(self.indexAt(self._startPos).data())
drag.setMimeData(mime)
drag.exec(Qt.MoveAction)
self._startPos = None
return
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self._startPos = None
super().mouseReleaseEvent(event)
请注意,Qt 项目视图已经支持拖放:要在自定义模型中启用该支持,您还需要在 flags()
中添加 Qt.ItemIsDragEnabled
并确保 table 支持通过使用 setDragEnabled(True)
(就像您所做的那样)或通过将视图的 dragDropMode
至少设置为 DragOnly
.
唯一剩下的“问题”是从拖动 mime 数据中获取 视图外部的数据,它使用内部格式序列化内容。
虽然这种方法可能看起来更复杂和困难,但如果您打算支持多个项目视图之间的拖放,它也是一个更好的解决方案,因为该序列化格式是所有 Qt 视图的通用和标准格式。
class CustomizedNumpyModel(QAbstractTableModel):
# ...
def flags(self, index):
return (Qt.ItemIsEnabled
| Qt.ItemIsSelectable
| Qt.ItemIsEditable
| Qt.ItemIsDragEnabled)
class PyTableWidget(QTableView):
def __init__(self, *args):
super().__init__(*args)
self.setDragEnabled(True)
# nothing else to implement in this class
class PyCustomButton(QPushButton):
def __init__(self, *args):
super().__init__()
self.setCursor(Qt.PointingHandCursor)
self.setAcceptDrops(True)
self._lista = []
def dragEnterEvent(self, event):
if 'application/x-qabstractitemmodeldatalist' in event.mimeData().formats():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
mimeData = event.mimeData()
if mimeData.hasText():
self._lista.append(mimeData.text())
elif 'application/x-qabstractitemmodeldatalist' in mimeData.formats():
names = []
stream = QDataStream(mimeData.data(
'application/x-qabstractitemmodeldatalist'))
while not stream.atEnd():
# all fields must be read, even if not used
row = stream.readInt()
column = stream.readInt()
for _ in range(stream.readInt()):
role = stream.readInt()
value = stream.readQVariant()
if role == Qt.DisplayRole:
names.append(value)
self._lista.extend(names)
print(self._lista)
注意 setData()
必须 always return 一个 bool。删除最后一个 else:
并将 return False
推回函数的主缩进级别。