PyQt5 QTableWidget 单元格select,保存并复制

PyQt5 QTableWidget cell select, save and copy

我加一个copy_button。当用户输入单元格时,用户想要 select 一行,然后单击 copy_button 复制内容并在 selected 行下方添加具有相同内容的新行。下面的代码应该完成它根据用户需要添加新行的工作,期望它的内容不是复制?我尝试打印以查看问题。我将 Qtable 小部件项目添加到空列表,然后在 for 循环之前打印该列表,看到它添加了内容。应该的,但是 setItem 方法后的项目打印,returns 为空。它与 table 的序列化过程相同。我还想序列化整个 table 并将其粘贴回去。

列出 for 循环前后的打印。

我的代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, Qt


class loadtable(QtWidgets.QTableWidget):
def __init__(self, parent=None):
    super(loadtable, self).__init__(1, 5,parent)



    self.setColumnCount(5)
    self.setRowCount(1)
    self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))   
    headertitle = ("A","B","C","D","E")
    QtWidgets.QTableWidgetItem(headertitle[i]))
    self.setHorizontalHeaderLabels(headertitle)
    self.verticalHeader().setVisible(False)
    self.horizontalHeader().setHighlightSections(False)
    self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
    self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
    self.setColumnWidth(0, 130)
    combox_lay = QtWidgets.QComboBox(self)
    combox_lay.addItems(["I","II"])
    self.setCellWidget(0, 4, combox_lay)


    self.cellChanged.connect(self._cellclicked)


def _cellclicked(self):
    self.value = self.currentItem()
    self.value.setTextAlignment(Qt.AlignCenter)

@QtCore.pyqtSlot()  
def _addrow(self):
    rowcount = self.rowCount()
    print(rowcount)
    self.setRowCount(rowcount+1)
    combox_add = QtWidgets.QComboBox(self)
    combox_add.addItems(["I","II"])
    self.setCellWidget(rowcount, 4, combox_add)

@QtCore.pyqtSlot()
def _removerow(self):
    if self.rowCount() > 0:
        self.removeRow(self.rowCount()-1)

@QtCore.pyqtSlot()
def _cellselected(self):
    r = self.currentRow()
    c = self.columnCount()
    cell = []
    for i in range(c):
        if i == c-1:
            it = self.cellWidget(r , i)
        else:
            it = self.item(r , i)
        cell.append(it)
    self.setcopy(cell,r,c)

def setcopy(self,cell,r,c):
    self.insertRow(r+1)
    print(cell)
    for j in range(c):
        if j < c-1:
            it = self.setItem(r+1, j,cell[j])
        else:
            it = self.setCellWidget(r+1, j, cell[j])
        print(it)
    return it    

class thirdtabloads(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(thirdtabloads, self).__init__(parent)      
        table = loadtable()


    button_layout = QtWidgets.QVBoxLayout()
    add_button = QtWidgets.QPushButton("Add")
    add_button.clicked.connect(table._addrow)
    delete_button = QtWidgets.QPushButton("Delete")
    delete_button.clicked.connect(table._removerow)
    copy_button = QtWidgets.QPushButton("Copy")
    copy_button.clicked.connect(table._cellselected)

    button_layout = QtWidgets.QVBoxLayout()
    button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
    button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)
    button_layout.addWidget(copy_button, alignment=QtCore.Qt.AlignTop)


    tablehbox = QtWidgets.QHBoxLayout()
    tablehbox.setContentsMargins(10,10,10,10)
    tablehbox.addWidget(table)

    grid = QtWidgets.QGridLayout(self)
    grid.addLayout(button_layout, 0, 1)
    grid.addLayout(tablehbox, 0, 0)        



if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = thirdtabloads()
    w.show()
    sys.exit(app.exec_())

首先,setItem()方法没有return任何东西,因为它是setter,所以如果你想找到如果项目存在,则必须使用 item() 方法,即 getter.

关于这个问题,您注意到您必须复制 2 个元素:QTableWidgetItem 和您使用 setCellWidget() 设置的小部件。如果你想复制 QTableWidgetItem ,你必须使用它的 clone() 方法,而对于小部件,没有方法可以做到这一点,所以你必须创建一个方法来复制必要的,在我的解决方案我展示了如何从 QComboBox 复制项目,如果您有其他小部件,则必须实现更多代码。最后总是检查,例如 currentRow 可以在没有选择任何东西时为 -1。

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

# copy qwidgets
def copy_widget(w):
    if isinstance(w, QtWidgets.QWidget):
        new_w = type(w)()
        if isinstance(w, QtWidgets.QComboBox):
            vals = [w.itemText(ix) for ix in range(w.count())]
            new_w.addItems(vals)

        # if instance(w, QtWidgets.AnotherWidget):
        #     copy values
        return new_w

class LoadTable(QtWidgets.QTableWidget):
    def __init__(self, parent=None):
        super(LoadTable, self).__init__(1, 5, parent)
        self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))   
        headertitle = ("A","B","C","D","E")
        self.setHorizontalHeaderLabels(headertitle)
        self.verticalHeader().hide()
        self.horizontalHeader().setHighlightSections(False)
        self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)

        self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.setColumnWidth(0, 130)

        combox_lay = QtWidgets.QComboBox(self)
        combox_lay.addItems(["I","II"])
        self.setCellWidget(0, 4, combox_lay)

        self.cellChanged.connect(self._cellclicked)

    @QtCore.pyqtSlot(int, int)
    def _cellclicked(self, r, c):
        it = self.item(r, c)
        it.setTextAlignment(QtCore.Qt.AlignCenter)        

    @QtCore.pyqtSlot()
    def _addrow(self):
        rowcount = self.rowCount()
        self.insertRow(rowcount)
        combox_add = QtWidgets.QComboBox(self)
        combox_add.addItems(["I","II"])
        self.setCellWidget(rowcount, 4, combox_add)

    @QtCore.pyqtSlot()
    def _removerow(self):
        if self.rowCount() > 0:
            self.removeRow(self.rowCount()-1)

    @QtCore.pyqtSlot()
    def _copyrow(self):
        r = self.currentRow()
        if 0 <= r < self.rowCount():
            cells = {"items": [], "widgets": []}
            for i in range(self.columnCount()):
                it = self.item(r, i)
                if it:
                    cells["items"].append((i, it.clone()))
                w = self.cellWidget(r, i)
                if w:
                    cells["widgets"].append((i, copy_widget(w)))
            self.copy(cells, r+1)

    def copy(self, cells, r):
        self.insertRow(r)
        for i, it in cells["items"]:
            self.setItem(r, i, it)
        for i, w in cells["widgets"]:
            self.setCellWidget(r, i, w)


class ThirdTabLoads(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ThirdTabLoads, self).__init__(parent)    

        table = LoadTable()

        add_button = QtWidgets.QPushButton("Add")
        add_button.clicked.connect(table._addrow)

        delete_button = QtWidgets.QPushButton("Delete")
        delete_button.clicked.connect(table._removerow)

        copy_button = QtWidgets.QPushButton("Copy")
        copy_button.clicked.connect(table._copyrow)

        button_layout = QtWidgets.QVBoxLayout()
        button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
        button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)
        button_layout.addWidget(copy_button, alignment=QtCore.Qt.AlignTop)

        tablehbox = QtWidgets.QHBoxLayout()
        tablehbox.setContentsMargins(10, 10, 10, 10)
        tablehbox.addWidget(table)

        grid = QtWidgets.QGridLayout(self)
        grid.addLayout(button_layout, 0, 1)
        grid.addLayout(tablehbox, 0, 0)        


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = ThirdTabLoads()
    w.show()
    sys.exit(app.exec_())