简体   繁体   中英

How to copy a row of QtableWidget and insert to the line below it?

I Want to have a table where each row has a button in the first cell of the QtableWidget and on the press of that button, the whole row gets duplicated with all the entries of the previous row including the button and the comboboxes.

I tried to copy the text of them and it was successful but it does not serve the purpose since again it requires to manually assign it to the comboboxes and etc. The attempt below, just insert a blank row on each click. How can the row gets fully duplicated with its elements?

ATTEMPT

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

In your case copying the row involves copying the widgets. From my experience I have come to the conclusion that you can not copy a widget (Qt does not allow it either), so instead of copying a widget you must copy more relevant features (1) of a widget.

The first thing is to identify the characteristics that make a row different from the other, in your case I have identified:

  • The data shown by the QComboBox
  • The selected index of the QComboBox.
  • Text from the third column

The other elements with your logic do not change (for example, your application does not allow modifying the text of the button).

Since we identified the features that distinguish the rows, those parameters must be those taken by the function that creates a row.

(1) This point is subjective

Considering the above, the solution is as follows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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