Copy/Paste multiple items from QTableView in pyqt4?

梦想与她 提交于 2019-11-29 12:47:01
self.tableView.installEventFilters(self)

Now, adding event filter:

def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.KeyPress and
            event.matches(QtGui.QKeySequence.Copy)):
            self.copySelection()
            return True
        return super(Window, self).eventFilter(source, event)

Copy Function:

def copySelection(self):
        selection = self.tableView.selectedIndexes()
        if selection:
            rows = sorted(index.row() for index in selection)
            columns = sorted(index.column() for index in selection)
            rowcount = rows[-1] - rows[0] + 1
            colcount = columns[-1] - columns[0] + 1
            table = [[''] * colcount for _ in range(rowcount)]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                table[row][column] = index.data()
            stream = io.StringIO()
            csv.writer(stream).writerows(table)
            QtGui.qApp.clipboard().setText(stream.getvalue())

Answered by ekhumoro, for the same question asked again.

QAbstractItemView.ExtendedSelection When the user selects an item in the usual way, the selection is cleared and the new item selected. However, if the user presses the Ctrl key when clicking on an item, the clicked item gets toggled and all other items are left untouched. If the user presses the Shift key while clicking on an item, all items between the current item and the clicked item are selected or unselected, depending on the state of the clicked item. Multiple items can be selected by dragging the mouse over them. you can also use

QAbstractItemView.MultiSelection

Many thanks to @learncode comment above, I manage to get the copy part. Moverover, I modify a bit to support copy to Excel with corresponding order of cells:

def copySelection(self):
    selection = self.selectedIndexes()
    if selection:
        rows = sorted(index.row() for index in selection)
        columns = sorted(index.column() for index in selection)
        rowcount = rows[-1] - rows[0] + 1
        colcount = columns[-1] - columns[0] + 1
        table = [[''] * colcount for _ in range(rowcount)]
        for index in selection:
            row = index.row() - rows[0]
            column = index.column() - columns[0]
            table[row][column] = index.data()
        stream = io.StringIO()
        csv.writer(stream, delimiter='\t').writerows(table)
        QtWidgets.qApp.clipboard().setText(stream.getvalue())
    return

In addition to copy, I also create the paste part. Depending the range of cell user selected (one cell or range of cell), this snippet supports pasting of different shape of data.

def pasteSelection(self):
    selection = self.selectedIndexes()
    if selection:
        model = self.model()

        buffer = QtWidgets.qApp.clipboard().text() 
        rows = sorted(index.row() for index in selection)
        columns = sorted(index.column() for index in selection)
        reader = csv.reader(io.StringIO(buffer), delimiter='\t')
        if len(rows) == 1 and len(columns) == 1:
            for i, line in enumerate(reader):
                for j, cell in enumerate(line):
                    model.setData(model.index(rows[0]+i,columns[0]+j), cell)
        else:
            arr = [ [ cell for cell in row ] for row in reader]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                model.setData(model.index(index.row(), index.column()), arr[row][column])
    return
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!