【问题标题】:In a QTableWidget, how to determine if an empty cell is editable?在 QTableWidget 中,如何确定空单元格是否可编辑?
【发布时间】:2017-04-07 11:59:27
【问题描述】:

我正在开发一个 QAction,将剪贴板中的结构化文本粘贴到 QTableWidget 中。这是我当前的代码:

class PasteCellsAction(qt.QAction):
    def __init__(self, table):
        if not isinstance(table, qt.QTableWidget):
            raise ValueError('CopySelectedCellsAction must be initialised ' +
                             'with a QTableWidget.')
        super(PasteCellsAction, self).__init__(table)
        self.table = table
        self.setText("Paste")
        self.setShortcut(qt.QKeySequence('Ctrl+V'))
        self.triggered.connect(self.pasteCellFromClipboard)

    def pasteCellFromClipboard(self):
        """Paste text from cipboard into the table.

        If the text contains tabulations and
        newlines, they are interpreted as column and row separators.
        In such a case, the text is split into multiple texts to be paste
        into multiple cells.

        :return: *True* in case of success, *False* if pasting data failed.
        """
        selected_idx = self.table.selectedIndexes()
        if len(selected_idx) != 1:
            msgBox = qt.QMessageBox(parent=self.table)
            msgBox.setText("A single cell must be selected to paste data")
            msgBox.exec_()
            return False

        selected_row = selected_idx[0].row()
        selected_col = selected_idx[0].column()

        qapp = qt.QApplication.instance()
        clipboard_text = qapp.clipboard().text()
        table_data = _parseTextAsTable(clipboard_text)

        protected_cells = 0
        out_of_range_cells = 0

        # paste table data into cells, using selected cell as origin
        for row in range(len(table_data)):
            for col in range(len(table_data[row])):
                if selected_row + row >= self.table.rowCount() or\
                   selected_col + col >= self.table.columnCount():
                    out_of_range_cells += 1
                    continue
                item = self.table.item(selected_row + row,
                                       selected_col + col)
                # ignore empty strings
                if table_data[row][col] != "":
                    if not item.flags() & qt.Qt.ItemIsEditable:
                        protected_cells += 1
                        continue
                    item.setText(table_data[row][col])

        if protected_cells or out_of_range_cells:
            msgBox = qt.QMessageBox(parent=self.table)
            msg = "Some data could not be inserted, "
            msg += "due to out-of-range or write-protected cells."
            msgBox.setText(msg)
            msgBox.exec_()
            return False
        return True

我想在粘贴数据之前测试一个单元格是否可编辑,为此我使用QTableWidget.item(row, col) 获取项目,然后检查项目的标志。

我的问题是.item 方法为空单元格返回None,所以我无法检查空单元格的标志。我的代码目前仅在粘贴区域中没有空单元格时才有效。

错误在第 46 行(None 返回)和第 50 行(AttributeError: 'NoneType' object has no attribute 'flags'):

            item = self.table.item(selected_row + row,
                                   selected_col + col)
            # ignore empty strings
            if table_data[row][col] != "":
                if not item.flags() & qt.Qt.ItemIsEditable:
                    ...

除了检查项目的标志之外,还有其他方法可以确定单元格是否可编辑?

【问题讨论】:

  • 返回None不是因为单元格为空,而是因为单元格不存在
  • 我不确定我是否理解这一点。我可以在表格小部件中直观地看到一个空单元格。你的意思是只要一个单元格中没有设置数据或标志,它就不作为一个项存在吗?
  • 如果答案是肯定的,是否不存在单元格保证是可编辑的?或者我的小部件的用户是否可以在不创建项目的情况下对其进行写保护?
  • 你确定selected_row + row, selected_col + col对应你看到的单元格的位置吗?
  • 是的,我很确定。当我将相同的数据粘贴到相同的位置时,该操作有效,只要我确保在粘贴之前向粘贴区域中的所有单元格添加一些随机文本。

标签: python qt pyqt qtablewidget


【解决方案1】:

QTableWidget 的尺寸可以在不显式添加任何项目的情况下指定。在这种情况下,单元格将完全为空 - 即数据和项目都是None。如果用户编辑单元格,数据将被添加到表格的模型中,并添加一个项目。即使输入的值为空字符串,也会发生这种情况。默认情况下,所有单元格都是可编辑的,除非您采取明确的步骤将它们设为只读。

有许多方法可以使单元格成为只读 - 例如,setting the edit triggers,或覆盖表格的 edit 方法。但是,如果您的 only 方法明确设置单个表格小部件项目的标志,您可以放心地假设没有项目的单元格既可编辑又为空。 (请注意,如果您直接通过表格的模型设置数据而不是使用例如setItem,则单元格仍然会自动有一个项目。

【讨论】:

  • 我已经切换到通过模型而不是小部件获取/设置数据,以使我的操作与 QTableView 以及 QTableWidget 一起工作。这消除了处理项目的需要。
【解决方案2】:

我找到了一个似乎可行的解决方案:当item() 方法返回None 时,创建一个新项目并将其添加到表中。

我仍然怀疑这是否存在修改写保护单元格标志的风险。我目前只是假设如果一个单元格被写保护,这意味着它一定已经包含一个项目。

            item = self.table.item(target_row,
                                   target_col)
            # item may not exist for empty cells
            if item is None:
                item = qt.QTableWidgetItem()
                self.table.setItem(target_row,
                                   target_col,
                                   item)
            # ignore empty strings
            if table_data[row_offset][col_offset] != "":
                if not item.flags() & qt.Qt.ItemIsEditable:
                    protected_cells += 1
                    continue
                item.setText(table_data[row_offset][col_offset])

编辑:target_row = selected_row + row_offset ...

【讨论】:

    猜你喜欢
    • 2020-06-06
    • 2016-11-13
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 2017-01-16
    相关资源
    最近更新 更多