【问题标题】:PyQt5 QTableWidget cell select, save and copyPyQt5 QTableWidget 单元格选择、保存和复制
【发布时间】:2019-02-20 19:38:44
【问题描述】:

As extension to my previous question我添加了一个复制按钮。当用户向单元格输入输入时,用户想要选择一行,然后单击 copy_button 复制内容并在所选行下方添加一个具有相同内容的新行。下面的代码假设完成它根据用户需要添加新行的工作,期望其内容不会复制?我尝试打印以查看问题。我将 Qtablewidget 项目添加到空列表中,然后在 for 循环之前打印列表,看到它添加了内容。正如它应该的那样,但是setItem 方法之后的项目打印返回空。它与表的序列化过程相同。我还想序列化整个表格并将其粘贴回来。

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

【问题讨论】:

    标签: python pyqt pyqt5 qtablewidget qbuttongroup


    【解决方案1】:

    首先,setItem() 方法不返回任何内容,因为它是一个 setter,所以如果你想知道该项是否存在,你必须使用 item() 方法是一个getter

    回到问题,您注意到您必须复制 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_())
    

    【讨论】:

    • 非常感谢您的解决方案。 {"items": [], "widgets": []} 这个代码!你会在字典中列出一个列表吗?你能解释一下,如果它:cells["items"].append((i, it.clone()))。会工作吗?
    • @ZarKha 正如您所注意到的,我正在字典中创建一个列表,该列表的元素是 2 个元素的元组,它们是列号和 QTableWidgetItem 的副本。如果我的回答对你有帮助,别忘了标记为正确,这是最好的感谢方式。
    猜你喜欢
    • 2020-06-28
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    相关资源
    最近更新 更多