python - 如何复制QtableWidget的一行并插入到它下面的行?

标签 python pyqt pyqt5

我想要一个表格,其中每行在 QtableWidget 的第一个单元格中都有一个按钮,按下该按钮时,整行将与前一行的所有条目(包括按钮和组合框)一起复制。

我尝试复制它们的文本并且成功了,但它没有达到目的,因为它再次需要手动将其分配给组合框等。 下面的尝试,只需在每次单击时插入一个空白行。该行如何与其元素完全重复?

尝试

from PyQt5 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.m_tablewidget = QtWidgets.QTableWidget(0, 3)
        self.m_tablewidget.setHorizontalHeaderLabels(
            ["Col 1", "Col 2", "Col 3"]
        )
        self.m_button = QtWidgets.QPushButton("Add Row", clicked=self.onClicked)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.m_tablewidget)
        lay.addWidget(self.m_button, alignment=QtCore.Qt.AlignLeft)

    def table_selector(self, tableName):
        variableSelected = []
        for r in range(tableName.rowCount()):
            row_variables = []
            for c in range(tableName.columnCount()):
                widget = tableName.cellWidget(r, c)
                if isinstance(widget, QtWidgets.QComboBox):
                    current_value = widget.currentText()
                    row_variables.append(current_value)
            variableSelected.append(row_variables)
        return variableSelected

    @QtCore.pyqtSlot()
    def addRow(self):

        rc = self.m_tablewidget.rowCount()
        self.m_tablewidget.insertRow(rc)

    @QtCore.pyqtSlot()
    def onClicked(self):
        d = {
            "a": ["x", "y", "z"],
            "b": ["4", "5", "6"],
            "c": ["21", "22", "23"],
        }

        combobox = QtWidgets.QComboBox()
        for k, v in d.items():
            combobox.addItem(k, v)

        item = QtWidgets.QTableWidgetItem()



        copyROw_button = QtWidgets.QPushButton("ADD ROW", clicked=self.addRow)

        rc = self.m_tablewidget.rowCount()
        self.m_tablewidget.insertRow(rc)

        for i, combo in enumerate((copyROw_button, combobox)):
            self.m_tablewidget.setCellWidget(rc, i, combo)




if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

最佳答案

在您的情况下,复制行涉及复制小部件。根据我的经验,我得出的结论是,您不能复制小部件(Qt 也不允许这样做),因此您必须复制更多相关功能 (1),而不是复制小部件 小部件。

第一件事是确定一行与另一行不同的特征,在您的情况下,我已经确定了:

  • QComboBox 显示的数据
  • QComboBox 的选定索引。
  • 第三列的文本

具有您逻辑的其他元素不会更改(例如,您的应用程序不允许修改按钮的文本)。

由于我们确定了区分行的特征,因此这些参数必须是创建行的函数所采用的参数。

(1) 这一点是主观的

综合以上情况,解决方案如下:

from PyQt5 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.m_tablewidget = QtWidgets.QTableWidget(0, 3)
        self.m_tablewidget.setHorizontalHeaderLabels(
            ["Col 1", "Col 2", "Col 3"]
        )
        self.m_button = QtWidgets.QPushButton("Add Row", clicked=self.onClicked)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.m_tablewidget)
        lay.addWidget(self.m_button, alignment=QtCore.Qt.AlignLeft)

    @QtCore.pyqtSlot()
    def addRow(self):
        button = self.sender()
        if not isinstance(button, QtWidgets.QPushButton):
            return
        p = button.mapTo(self.m_tablewidget.viewport(), QtCore.QPoint())
        ix = self.m_tablewidget.indexAt(p)
        if not ix.isValid() or ix.column() != 0:
            return
        r = ix.row()
        ix_combobox = 0
        text = ""
        combo = self.m_tablewidget.cellWidget(r, 1)
        if isinstance(combo, QtWidgets.QComboBox):
            ix_combobox = combo.currentIndex()
        item = self.m_tablewidget.item(r, 2)
        if item is not None:
            text = item.text()
        self.insert_row(row=r + 1, ix_combobox=ix_combobox, text=text)

    @QtCore.pyqtSlot()
    def onClicked(self):
        self.insert_row()

    def insert_row(self, d=None, ix_combobox=0, text="", row=-1):
        if d is None:
            d = {
                "a": ["x", "y", "z"],
                "b": ["4", "5", "6"],
                "c": ["21", "22", "23"],
            }
        combobox = QtWidgets.QComboBox()
        for k, v in d.items():
            combobox.addItem(k, v)
        combobox.setCurrentIndex(ix_combobox)
        item = QtWidgets.QTableWidgetItem()
        copyROw_button = QtWidgets.QPushButton("ADD ROW", clicked=self.addRow)
        if row == -1:
            row = self.m_tablewidget.rowCount()
        self.m_tablewidget.insertRow(row)
        for i, combo in enumerate((copyROw_button, combobox)):
            self.m_tablewidget.setCellWidget(row, i, combo)
        if text:
            self.m_tablewidget.setItem(row, 2, QtWidgets.QTableWidgetItem(text))


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())

关于python - 如何复制QtableWidget的一行并插入到它下面的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56763446/

相关文章:

python - 如何在 PyQt5 中捕获悬停和鼠标离开信号

python - 以交错方式组合两个 Python 列表

python - tensorflow 张量板错误: you must feed a value for placeholder tensor

python - Django - 静态文件夹不在基础项目中

python - Ubuntu vs OSX 和 SSD vs HDD 上的多处理

python - PyQt QTabBar 不创建新选项卡

python - QtQuick GeometryChanged 方法仅适用于加载组件的一个方向

python - 为什么我的 python 类继承不正确?

python - query.next() 慢吗?

resize - 使 QTreeView 自动调整内容大小