从PyQt中的表格小部件中选择多行后,单元格小部件按钮显示在错误的位置

问题描述

我想用每行两个按钮创建一个表小部件,并在插入行后选择一些行。

以编程方式选择行之后,我发现表格中的按钮移至错误的位置。如果我只选择一行,那么一切都很好。

根据@eyllanesc的建议,我试图重现此问题,但是从下面的代码中看起来不错。我的代码在QGIS上运行,而不是在纯PyQt5上运行,因此我无法真正复制它。

我不知道为什么会发生此问题以及如何解决此问题。 有没有一种方法可以重置单元格小部件的位置?或者我可以手动设置单元小部件的位置。如果可能的话,也许我可以找到一种方法来重新设置它。谢谢。

我的代码如下:

from PyQt5 import QtCore,QtGui,QtWidgets

class Ui_Dialog(object):
    def setupUi(self,Dialog):
        Dialog.setobjectName("Dialog")
        Dialog.resize(400,200)
        self.gridLayout = QtWidgets.qgridLayout(Dialog)
        self.gridLayout.setobjectName("gridLayout")

        # add a button on the window
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setText("add rows")
        self.gridLayout.addWidget(self.pushButton,1,6,1)

        self.tableWidget = QtWidgets.QTableWidget(Dialog)
        self.tableWidget.setMinimumSize(QtCore.QSize(0,0))
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setobjectName("tableWidget")
        self.tableWidget.setRowCount(0)
        self.tableWidget.horizontalHeader().setVisible(True)
        self.tableWidget.horizontalHeader().setDefaultSectionSize(150)
        self.tableWidget.horizontalHeader().setMinimumSectionSize(39)
        self.tableWidget.horizontalHeader().setStretchLastSection(True)
        self.tableWidget.verticalHeader().setDefaultSectionSize(45)
        self.tableWidget.verticalHeader().setMinimumSectionSize(35)
        self.tableWidget.setMinimumSize(450,260)
        # set column count
        self.tableWidget.setColumnCount(3)
        # add two rows
        ui.tableWidget.setRowCount(2)
        for i in range(2):
            # button 1 of column1
            pushButton1 = QtWidgets.QPushButton(ui.tableWidget)
            pushButton1.setText('a' + str(i))
            ui.tableWidget.setCellWidget(i,pushButton1)

            # button 2 of column2
            pushButton2 = QtWidgets.QPushButton(ui.tableWidget)
            pushButton2.setText('b' + str(i))
            ui.tableWidget.setCellWidget(i,pushButton2)

            # an item of column3
            qItem = QtWidgets.QTableWidgetItem(str(i))
            ui.tableWidget.setItem(i,2,qItem)
            qItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable)

        self.gridLayout.addWidget(self.tableWidget,7)


        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self,Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setwindowTitle(_translate("Dialog",""))
        self.tableWidget.setSortingEnabled(True)

    def addRows(self):
        # change to mutiple selection mode
        self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        
        # insert three new rows and select them
        for i in range(3):
            row = self.insertRow()
            # select the row
            self.tableWidget.selectRow(row)
        
        # change select mode back
        self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
    
    def insertRow(self):
         # insert a row to the table
        rowCount = self.tableWidget.rowCount()
        self.tableWidget.insertRow(rowCount)
        
        # row to insert 
        row = self.tableWidget.rowCount() - 1

        # button 1 of column1
        pushButton1 = QtWidgets.QPushButton(self.tableWidget)
        pushButton1.setText('a' + str(row))
        self.tableWidget.setCellWidget(row,pushButton1)

        # button 2 of column2
        pushButton2 = QtWidgets.QPushButton(self.tableWidget)
        pushButton2.setText('b' + str(row))
        self.tableWidget.setCellWidget(row,pushButton2)

        # an item of column3
        qItem = QtWidgets.QTableWidgetItem(str(row))
        self.tableWidget.setItem(row,qItem)
        qItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable)
    
        return row


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Dialog = QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(Dialog)
    ui.pushButton.clicked.connect(ui.addRows)
    Dialog.show()
    sys.exit(app.exec_())

该表的屏幕截图为:

enter image description here

enter image description here

解决方法

我无法在QGIS之外重现该问题。但是在玩了之后,我找到了解决问题的方法。

因此,在插入一些记录后,我将对按钮列上的表调用sortItems(),然后所有按钮将显示在正确的位置。不知道为什么,但是对我有用。

tableWidget.sortItems(0)
,

只需添加按钮并连接代码即可。您需要启用排序。我也不确定为什么要使用扩展选择。希望下面的代码能解决您的问题。

from PyQt5 import QtCore,QtGui,QtWidgets


class Ui_MainWindow(object):
    def setupUi(self,MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1020,950)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(9,9,581,211))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(3)
        self.tableWidget.setRowCount(5)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(0,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(1,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(2,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(3,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(4,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(0,1,item)
        item = QtWidgets.QTableWidgetItem()

        item = QtWidgets.QPushButton("its a button")
        
        self.tableWidget.setCellWidget(0,2,item)
        
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(2,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(3,item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(4,item)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0,1020,21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self,MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow","MainWindow"))
        item = self.tableWidget.verticalHeaderItem(0)
        item.setText(_translate("MainWindow","Row1"))
        item = self.tableWidget.verticalHeaderItem(1)
        item.setText(_translate("MainWindow","Row2"))
        item = self.tableWidget.verticalHeaderItem(2)
        item.setText(_translate("MainWindow","Row3"))
        item = self.tableWidget.verticalHeaderItem(3)
        item.setText(_translate("MainWindow","Row4"))
        item = self.tableWidget.verticalHeaderItem(4)
        item.setText(_translate("MainWindow","Row5"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow","Col1"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow","Col2"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow","Col3"))
        __sortingEnabled = self.tableWidget.isSortingEnabled()
        self.tableWidget.setSortingEnabled(False)
        item = self.tableWidget.item(0,0)
        item.setText(_translate("MainWindow","1"))
        item = self.tableWidget.item(0,1)
        
        item.setText(_translate("MainWindow","1"))
        item = self.tableWidget.item(1,"2"))
        item = self.tableWidget.item(1,1)
        item.setText(_translate("MainWindow",2)
        item.setText(_translate("MainWindow","2"))
        item = self.tableWidget.item(2,"3"))
        item = self.tableWidget.item(2,"3"))
        item = self.tableWidget.item(3,"4"))
        item = self.tableWidget.item(3,"4"))
        item = self.tableWidget.item(4,"5"))
        item = self.tableWidget.item(4,"5"))
        self.tableWidget.setSortingEnabled(__sortingEnabled)



if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())