Ячейка PyQt5 QTableWidget выбирает, сохраняет и копирует

В качестве дополнения к моему предыдущему вопросу я добавляю copy_button. Когда пользователь вводит данные в ячейки, и пользователь хочет выбрать строку и нажать на кнопку copy_button, чтобы скопировать содержимое и добавить новую строку под выбранной строкой с тем же содержимым. Приведенный ниже код предполагает, что для выполнения работы он добавляет новую строку по желанию пользователя, ожидая, что его содержимое не копируется с? Я попытался напечатать, чтобы увидеть проблему. Я добавляю элементы Qtablewidget в пустой список, затем список печатается перед циклом for, видит, что к нему добавлено содержимое. как положено, но распечатка предметов после setItem метод, возвращает пустой. Это та же процедура, что и при сериализации таблицы. Я хочу также сериализовать всю таблицу и вставить ее обратно.

Список печати до и после цикла.

Мой код:

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 ответ

Решение

Прежде всего, setItem() Метод ничего не возвращает, так как он является установщиком, поэтому, если вы хотите узнать, существует ли элемент, вы должны использовать item() метод, который является добытчиком.

Переходя к проблеме, вы заметили, что вы должны скопировать 2 элемента: QTableWidgetItems и виджеты, которые вы установили с 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_())
Другие вопросы по тегам