复制PyQt表格选择,包括列和行标题
我想复制一个qt表格中选中的部分,包括表头。默认情况下,qt表格只会复制一个单元格,而我需要复制整个选中的区域,这可能包含多列和多行。我从不同地方拼凑了一些代码(主要是这里的),看起来运行得不错,但它只复制了单元格里的数据,没有复制表头。我需要一些帮助来获取选中部分的表头。以下是我简化后的示例:
from PyQt4 import QtGui, QtCore
import sys
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.table = QtGui.QTableWidget(parent=self)
self.table.setColumnCount(2)
self.table.setRowCount(2)
self.table.setHorizontalHeaderLabels(['col1','col2'])
self.table.setVerticalHeaderLabels(['row1','row2'])
self.table.setItem(0,0,QtGui.QTableWidgetItem('foo'))
self.table.setItem(0,1,QtGui.QTableWidgetItem('bar'))
self.table.setItem(1,0,QtGui.QTableWidgetItem('baz'))
self.table.setItem(1,1,QtGui.QTableWidgetItem('qux'))
layout = QtGui.QGridLayout()
layout.addWidget(self.table, 1, 0)
self.setLayout(layout)
self.clip = QtGui.QApplication.clipboard()
def keyPressEvent(self, e):
if (e.modifiers() & QtCore.Qt.ControlModifier):
selected = self.table.selectedRanges()
if e.key() == QtCore.Qt.Key_C: #copy
s = ""
for r in xrange(selected[0].topRow(), selected[0].bottomRow()+1):
for c in xrange(selected[0].leftColumn(), selected[0].rightColumn()+1):
try:
s += str(self.table.item(r,c).text()) + "\t"
except AttributeError:
s += "\t"
s = s[:-1] + "\n" #eliminate last '\t'
self.clip.setText(s)
if __name__ == '__main__':
# Initialize the application
app = QtGui.QApplication(sys.argv)
mw = MainWidget()
mw.show()
app.exec_()
这个示例表格看起来是这样的:
col1 col2
row1 foo bar
row2 baz qux
举个例子,如果我选中了bar
和bux
,我希望复制的内容是:
\t col2\n
row1 \t bar\n
row2 \t qux\n
我实际的情况有很多列和行。我遇到的困难是如何获取选中单元格的表头;格式方面我可以处理。任何帮助或建议都非常感谢。提前谢谢你们!
2 个回答
0
我知道这个问题有点老了,但对于那些想要找到可以选择多个不相连的区域的解决方案的人来说,下面的代码对我来说是有效的。
def copy_selection_to_clipboard(self) -> None:
def intersects_with_ranges(ranges: list[tuple[int, int, int, int]], row: int, col: int) -> bool:
# Checks if given row and col is in any given range
for range_ in ranges:
top, left, bottom, right = range_
in_between_rows = row >= top and row <= bottom
in_between_cols = col >= left and col <= right
if in_between_rows and in_between_cols:
return True
return False
model = self.model()
ranges = [(r.topRow(), r.leftColumn(), r.bottomRow(), r.rightColumn()) for r in self.selectedRanges()]
is_whole_table_selected = (
len(ranges) == 1
and ranges[0][0] == 0
and ranges[0][1] == 0
and ranges[0][2] == self.rowCount() - 1
and ranges[0][3] == self.columnCount() - 1
)
row_start = min(ranges, key=lambda r: r[0])[0]
col_start = min(ranges, key=lambda r: r[1])[1]
row_end = max(ranges, key=lambda r: r[2])[2]
col_end = max(ranges, key=lambda r: r[3])[3]
rows = []
for row_idx in range(row_start, row_end + 1):
row = []
for col_idx in range(col_start, col_end + 1):
# empty value for not selected columns
if not is_whole_table_selected and not intersects_with_ranges(ranges, row_idx, col_idx):
value = ""
else:
# could also use EditRole if you have a customed model and want the raw value
value = model.index(row_idx, col_idx).data(QtCore.Qt.ItemDataRole.DisplayRole)
row.append(value)
rows.append(row)
if is_whole_table_selected:
rows.insert(0, [self.horizontalHeaderItem(i).text() for i in range(self.columnCount())])
clipboard_text = "\r\n".join("\t".join(row) for row in rows)
QtWidgets.QApplication.clipboard().setText(clipboard_text)
然后只需为表格添加一个操作,使用 Ctrl + C
组合键。
action = self.addAction("Auswahl kopieren")
action.setShortcut(QtGui.QKeySequence("Ctrl+C"))
action.triggered.connect(self.copy_selection_to_clipboard)
(这段代码假设你是从 QTableWidget
继承过来的)
5
提示在于头部项目:
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.table = QtGui.QTableWidget(parent=self)
self.table.setColumnCount(2)
self.table.setRowCount(2)
self.table.setHorizontalHeaderLabels(['col1','col2'])
self.table.setVerticalHeaderLabels(['row1','row2'])
self.table.setItem(0,0,QtGui.QTableWidgetItem('foo'))
self.table.setItem(0,1,QtGui.QTableWidgetItem('bar'))
self.table.setItem(1,0,QtGui.QTableWidgetItem('baz'))
self.table.setItem(1,1,QtGui.QTableWidgetItem('qux'))
layout = QtGui.QGridLayout()
layout.addWidget(self.table, 1, 0)
self.setLayout(layout)
self.clip = QtGui.QApplication.clipboard()
def keyPressEvent(self, e):
if (e.modifiers() & QtCore.Qt.ControlModifier):
selected = self.table.selectedRanges()
if e.key() == QtCore.Qt.Key_C: #copy
s = '\t'+"\t".join([str(self.table.horizontalHeaderItem(i).text()) for i in xrange(selected[0].leftColumn(), selected[0].rightColumn()+1)])
s = s + '\n'
for r in xrange(selected[0].topRow(), selected[0].bottomRow()+1):
s += self.table.verticalHeaderItem(r).text() + '\t'
for c in xrange(selected[0].leftColumn(), selected[0].rightColumn()+1):
try:
s += str(self.table.item(r,c).text()) + "\t"
except AttributeError:
s += "\t"
s = s[:-1] + "\n" #eliminate last '\t'
self.clip.setText(s)