PyQt5 QTableWidget cell select, save and copy

て烟熏妆下的殇ゞ 提交于 2020-01-24 20:14:50

问题


As extension to my previous question I add a copy_button. When user enter input to cells, and user would like select a row, and click on copy_button to copy contents and add an new row below the selected row with same content. The code below supposes to do the job it adds a new row as user wants, expect from its contents is not copying with? I tried to print to see the problem. I add Qtablewidget items to empty list, then the list is printed before for loop, sees it has content added to it. as it should, but a print of items after setItem method, returns empty. It is the same procedure as serializing of the table. I want also to serialize whole table and paste it back.

List print before and after for loop.

My code:

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

回答1:


First of all, the setItem() method does not return anything since it is a setter, so if you want to find out if the item exists, you must use the item() method that is a getter.

Going to the problem, you have noticed that you must copy 2 elements: the QTableWidgetItems and the widgets that you set with setCellWidget(). If you want to copy the QTableWidgetItem you must use its clone() method, and in the case of the widget there is no method to do it so you will have to create a method that copies the necessary, in my solution I show how to copy the items from a QComboBox, if you have other widgets you will have to implement more code. Finally always check, for example currentRow can be -1 when nothing has been selected.

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


来源:https://stackoverflow.com/questions/52358258/pyqt5-qtablewidget-cell-select-save-and-copy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!