PyQt5 QTableWidget 单元格选择、保存和复制 [英] PyQt5 QTableWidget cell select, save and copy

查看:167
本文介绍了PyQt5 QTableWidget 单元格选择、保存和复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

在 for 循环之前和之后列出打印.

List print before and after for loop.

我的代码:

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() 方法不返回任何内容,因为它是一个 setter,所以如果你想知道这个项目是否存在,你必须使用 item() 方法,它是一个 getter.

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.

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

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

这篇关于PyQt5 QTableWidget 单元格选择、保存和复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆