问题描述
我有一个在 Qt 中使用 qtableview 构建的表,其模型由 qabstracttablemodel 构建,该模型从 pandas dataframe 获取数据。我希望能够使用全局剪贴板复制和粘贴单元格的内容。我在 PyQt4 和其他人中找到了几个例子 here、here 和 here 但是,我仍然无法将任何内容写入剪贴板。我的方法感觉有点蛮力,所以我希望有一种更 Python 化的 Qt'esk 方法。
这是我的表类:
class MyTableView(QTableView):
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
def send_to_clipboard(self):
# get selected contents from clipboard: List[QModelIndex]
cells = self.selectedindexes()
# check for contents
if not cells:
return
# set initial values to first cell
r = cells[0].row()
c = cells[0].column()
text = cells[0].data()
# skip first cell and iterate over rest to make tab delineated content
for i in range(len(cells) - 1):
if cells[i+1].row() == r:
text += f'\t{cells[i+1].data()}'
continue
r += 1
text += '\n'
# send text to clipboard
clipboard = QApplication.instance().clipboard()
clipboard.clear()
# strip trailing \n for data set and post to clipboard
clipboard.setText(text.strip())
def get_from_clipboard(self):
# pull clipboard data and split into rows
clipboard = QApplication.clipboard()
rows = clipboard.text().split('\n')
# and split again into column data
row_col_data = [[data for data in row.split('\t')] for row in rows]
# get past location and populate with data
r = self.currentRow()
c = self.currentColumn()
for row in row_col_data:
for data in row:
self.setItem(r,c,QTableWidgetItem(data))
self.model()
c += 1
r += 1
def keyPressEvent(self,e: QtGui.QKeyEvent) -> None:
super().keyPressEvent(e)
if e.key() == Qt.Key_C and (e.modifiers() & Qt.ControlModifier):
self.send_to_clipboard()
elif e.key() == Qt.Key_V and (e.modifiers() & Qt.ControlModifier):
self.get_from_clipboard()
这是我的模型:
class DataFrameModel(QAbstractTableModel):
DtypeRole = Qt.UserRole + 1000
ValueRole = Qt.UserRole + 1001
def __init__(self,df=pd.DataFrame(),parent=None):
super(DataFrameModel,self).__init__(parent)
self._dataframe = df
self.editable = False
def setDataFrame(self,dataframe):
self.beginResetModel()
self._dataframe = dataframe.copy()
self.endResetModel()
def dataFrame(self):
return self._dataframe
dataFrame = pyqtProperty(pd.DataFrame,fget=dataFrame,fset=setDataFrame)
@pyqtSlot(int,Qt.Orientation,result=str)
def headerData(self,section: int,orientation: Qt.Orientation,role: int = Qt.displayRole):
if role == Qt.displayRole:
if orientation == Qt.Horizontal:
return self._dataframe.columns[section]
else:
return str(self._dataframe.index[section])
return QVariant()
def rowCount(self,parent=QModelIndex()):
if parent.isValid():
return 0
return len(self._dataframe.index)
def columnCount(self,parent=QModelIndex()):
if parent.isValid():
return 0
return self._dataframe.columns.size
def data(self,index,role=Qt.displayRole):
if not index.isValid() or not (0 <= index.row() < self.rowCount()
and 0 <= index.column() < self.columnCount()):
return QVariant()
row = self._dataframe.index[index.row()]
col = self._dataframe.columns[index.column()]
dt = self._dataframe[col].dtype
val = self._dataframe.iloc[row][col]
if role == Qt.displayRole:
return str(val)
if role == DataFrameModel.ValueRole:
return val
if role == DataFrameModel.DtypeRole:
return dt
if role == Qt.ToolTipRole:
return str(val)
if role == Qt.EditRole:
return str(val)
return QVariant()
def roleNames(self):
roles = {
Qt.displayRole: b'display',DataFrameModel.DtypeRole: b'dtype',DataFrameModel.ValueRole: b'value',Qt.ToolTipRole: b'tooltip'
}
return roles
def setData(self,value,role: int = Qt.EditRole):
if not index.isValid() or role != Qt.EditRole:
return False
row = index.row()
if row < 0 or row >= len(self._dataframe.values):
return False
column = index.column()
if column < 0 or column >= self._dataframe.columns.size:
return False
self._dataframe.iloc[row][column] = value
self.dataChanged.emit(index,index)
return True
def flags(self,index):
flags = super(self.__class__,self).flags(index)
flags |= Qt.ItemIsSelectable
if self.editable:
flags |= Qt.ItemIsEditable
flags |= Qt.ItemIsEnabled
flags |= Qt.ItemIsDragEnabled
flags |= Qt.ItemIsDropEnabled
return flags
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)