简体   繁体   English

从 pyqt4 中的 QTableView 复制/粘贴多个项目?

[英]Copy/Paste multiple items from QTableView in pyqt4?

We can select multiple items(partial rows and partial columns) from QTableView using self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection) , but after selecting some rows and columns(partial and partial) if I do CTRL + C and paste it in notepad it only pastes one item(one value from the tableView)?我们可以使用self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection) ) 从 QTableView 选择多个项目(部分行和部分列),但是在选择一些行和列(部分和部分)之后,如果我执行CTRL + C并将其粘贴到记事本中只粘贴一项(tableView 中的一个值)?

My Code:我的代码:

tab_table_view = QtGui.QWidget()
self.Tab.insertTab(0, tab_table_view, self.File_Name)
self.tableView = QtGui.QTableView(tab_table_view)
self.tableView.setGeometry(QtCore.QRect(0, 0, 721, 571))
self.model = QtGui.QStandardItemModel(self)
self.model.setSortRole(QtCore.Qt.UserRole)
self.tableView.setModel(self.model)

    self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection) '''this helps for selecting multiple items but not able to copy and paste multiple values to a text/ excel (it only copies single value)'''

How can we do copy and paste multiple items?我们如何复制和粘贴多个项目?

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())       

Many thanks to @learncode comment above, I manage to get the copy part.非常感谢上面的@learncode 评论,我设法获得了复制部分。 Moverover, I modify a bit to support copy to Excel with corresponding order of cells: Moverover,我修改了一下以支持复制到具有相应单元格顺序的 Excel:

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

QAbstractItemView.ExtendedSelection When the user selects an item in the usual way, the selection is cleared and the new item selected. QAbstractItemView.ExtendedSelection当用户以通常的方式选择一个项目时,选择被清除并选择新项目。 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 .但是,如果用户在单击某个项目时按下 Ctrl 键,则单击的项目将被切换,而所有其他项目都保持不变 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.如果用户在单击 item 的同时按下Shift 键,则当前 item 和被单击 item 之间的所有 item 被选中或取消选中,具体取决于被单击 item 的状态。 Multiple items can be selected by dragging the mouse over them.可以通过将鼠标拖到多个项目上来选择它们。 you can also use你也可以使用

QAbstractItemView.MultiSelection

This answer extends @learncode and @Frederick Li's answers to cater for the cases where这个答案扩展了@learncode 和@Frederick Li 的答案,以适应以下情况

  1. The rows and columns are not in ascending order行和列不按升序排列
  2. Some of the rows and/or columns are hidden in the view.某些行和/或列隐藏在视图中。

It also includes code to extend the event filter to handle pasting.它还包括扩展事件过滤器以处理粘贴的代码。

class TableView(QTableView):
    def __init__(self, *args, **kwargs):
        super(TableView, self).__init__(*args, **kwargs)
        self.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QEvent.KeyPress and event.matches(QKeySequence.Copy):
            self.copy_selection()
            return True
        elif event.type() == QEvent.KeyPress and event.matches(QKeySequence.Paste):
            self.paste_selection()
            return True
        return super(TableView, self).eventFilter(source, event)

    def copy_selection(self):
        selection = self.selectedIndexes()
        if selection:
            all_rows = []
            all_columns = []
            for index in selection:
                if not index.row() in all_rows:
                    all_rows.append(index.row())
                if not index.column() in all_columns:
                    all_columns.append(index.column())
            visible_rows = [row for row in all_rows if not self.isRowHidden(row)]
            visible_columns = [
                col for col in all_columns if not self.isColumnHidden(col)
            ]
            table = [[""] * len(visible_columns) for _ in range(len(visible_rows))]
            for index in selection:
                if index.row() in visible_rows and index.column() in visible_columns:
                    selection_row = visible_rows.index(index.row())
                    selection_column = visible_columns.index(index.column())
                    table[selection_row][selection_column] = index.data()
            stream = io.StringIO()
            csv.writer(stream, delimiter="\t").writerows(table)
            QApplication.clipboard().setText(stream.getvalue())

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

            buffer = QApplication.clipboard().text()
            all_rows = []
            all_columns = []
            for index in selection:
                if not index.row() in all_rows:
                    all_rows.append(index.row())
                if not index.column() in all_columns:
                    all_columns.append(index.column())
            visible_rows = [row for row in all_rows if not self.isRowHidden(row)]
            visible_columns = [
                col for col in all_columns if not self.isColumnHidden(col)
            ]

            reader = csv.reader(io.StringIO(buffer), delimiter="\t")
            arr = [[cell for cell in row] for row in reader]
            if len(arr) > 0:
                nrows = len(arr)
                ncols = len(arr[0])
                if len(visible_rows) == 1 and len(visible_columns) == 1:
                    # Only the top-left cell is highlighted.
                    for i in range(nrows):
                        insert_rows = [visible_rows[0]]
                        row = insert_rows[0] + 1
                        while len(insert_rows) < nrows:
                            row += 1
                            if not self.isRowHidden(row):
                                insert_rows.append(row)                              
                    for j in range(ncols):
                        insert_columns = [visible_columns[0]]
                        col = insert_columns[0] + 1
                        while len(insert_columns) < ncols:
                            col += 1
                            if not self.isColumnHidden(col):
                                insert_columns.append(col)
                    for i, insert_row in enumerate(insert_rows):
                        for j, insert_column in enumerate(insert_columns):
                            cell = arr[i][j]
                            model.setData(model.index(insert_row, insert_column), cell)
                else:
                    # Assume the selection size matches the clipboard data size.
                    for index in selection:
                        selection_row = visible_rows.index(index.row())
                        selection_column = visible_columns.index(index.column())
                        model.setData(
                            model.index(index.row(), index.column()),
                            arr[selection_row][selection_column],
                        )
        return

Copy and paste of single selection of multiple items can be done in c++ by overriding Keypressevent of QTableView可以通过覆盖 QTableView 的 Keypressevent 在 c++ 中完成对多个项目的单选复制和粘贴

void CustomTableView::keyPressEvent(QKeyEvent *event)
{

    this->setSelectionBehavior(QAbstractItemView::SelectRows);
        this->setSelectionMode(QAbstractItemView::MultiSelection);
        QModelIndexList selectedRows = selectionModel()->selectedRows();
        QModelIndexList selectedColumns = selectionModel()->selectedColumns();
    if(event->key() == Qt::Key_Insert)
    {
        tblview_model->customInsertRows();
    }
    else if(event->key() == Qt::Key_Delete)
    {  if(!selectedRows.isEmpty())
            model()->removeRows(selectedRows.at(0).row(),
                                selectedRows.size());
    }
    else if(event->matches(QKeySequence::Paste)) {
        if(copyPasteEnabled == true){
            text = QApplication::clipboard()->text();
            if(!text.isEmpty()){
                tblview_model->pasteData(text);
            }
        }
    }

    if(!selectedIndexes().isEmpty()){
        if(event->matches(QKeySequence::Copy)){
            QString text;
            QStringList hdr_lst;
            const std::vector<std::string>& hdrs = tblview_model->getHeader();

            QItemSelectionRange range = selectionModel()->selection().first();
            if (!selectedColumns.isEmpty())
            {
                for (auto j = 0; j < selectedColumns.size(); ++j)
                {
                    std::string hd = hdrs[selectedColumns.at(j).column()];
                    if (std::find(hdrs.begin(), hdrs.end(), hd) != hdrs.end())
                        hdr_lst << QString::fromStdString(hd);
                }
                text += hdr_lst.join("\t");
                text += "\n";

                for (auto i = 0; i < tblview_model->rowCount(); ++i)
                {
                    QStringList rowContents;
                    for (auto j = 0; j < selectedColumns.size(); ++j)
                    {
                        if (!isColumnHidden(j)) {
                            rowContents << model()->index(i, selectedColumns.at(j).column()).data().toString();
                        }
                    }
                    text += rowContents.join("\t");
                    text += "\n";
                }
            }
            else if (!selectedRows.isEmpty())
            {
                for (auto h : hdrs)
                {
                    hdr_lst << QString::fromStdString(h);
                }

                text += hdr_lst.join("\t");
                text += "\n";
                //for (auto i = range.top(); i <= range.bottom(); ++i)
                for (auto i = 0; i < selectedRows.size(); ++i)
                {
                    QStringList rowContents;
                    for (auto j = 0; j <= tblview_model->columnCount(); ++j)
                    {
                        if (!isColumnHidden(j)) {
                            rowContents << model()->index(selectedRows.at(i).row(), j).data().toString();
                        }
                    }
                    text += rowContents.join("\t");
                    text += "\n";
                }
            }
            QApplication::clipboard()->setText(text);
        }
        else
            QTableView::keyPressEvent(event);
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM