从 PyQt 中的表格小部件中选择多行后,单元格小部件(按钮)显示在错误的位置
Posted
技术标签:
【中文标题】从 PyQt 中的表格小部件中选择多行后,单元格小部件(按钮)显示在错误的位置【英文标题】:After selecting multiple rows from a table widget in PyQt, the cell widget(button) is shown in a wrong position 【发布时间】:2020-09-04 13:56:54 【问题描述】:我想创建一个表格小部件,每行有两个按钮,并在插入行后选择一些行。
以编程方式选择行后,我发现表格中的按钮被移动到错误的位置。如果我只选择一行,一切都很好。
根据@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, 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, 0, pushButton1)
# button 2 of column2
pushButton2 = QtWidgets.QPushButton(ui.tableWidget)
pushButton2.setText('b' + str(i))
ui.tableWidget.setCellWidget(i, 1, 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, 0, 0, 1, 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, 0, pushButton1)
# button 2 of column2
pushButton2 = QtWidgets.QPushButton(self.tableWidget)
pushButton2.setText('b' + str(row))
self.tableWidget.setCellWidget(row, 1, pushButton2)
# an item of column3
qItem = QtWidgets.QTableWidgetItem(str(row))
self.tableWidget.setItem(row, 2, 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_())
表格截图如下:
【问题讨论】:
请提供minimal reproducible example 【参考方案1】:我未能在 QGIS 之外重现该问题。但是在玩弄之后,我找到了解决问题的方法。
所以在插入一些记录后,我在按钮列上的表格中调用 sortItems(),然后所有按钮将显示在正确的位置。不知道为什么,但它对我有用。
tableWidget.sortItems(0)
【讨论】:
【参考方案2】:只需添加按钮并连接您的代码。您需要启用排序。我也不确定你为什么要使用扩展选择。我希望下面的代码可以解决您的问题。
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, 0, 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, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(2, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(2, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(2, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(3, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(3, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(3, 2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(4, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(4, 1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(4, 2, item)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 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, 0)
item.setText(_translate("MainWindow", "2"))
item = self.tableWidget.item(1, 1)
item.setText(_translate("MainWindow", "2"))
item = self.tableWidget.item(1, 2)
item.setText(_translate("MainWindow", "2"))
item = self.tableWidget.item(2, 0)
item.setText(_translate("MainWindow", "3"))
item = self.tableWidget.item(2, 1)
item.setText(_translate("MainWindow", "3"))
item = self.tableWidget.item(2, 2)
item.setText(_translate("MainWindow", "3"))
item = self.tableWidget.item(3, 0)
item.setText(_translate("MainWindow", "4"))
item = self.tableWidget.item(3, 1)
item.setText(_translate("MainWindow", "4"))
item = self.tableWidget.item(3, 2)
item.setText(_translate("MainWindow", "4"))
item = self.tableWidget.item(4, 0)
item.setText(_translate("MainWindow", "5"))
item = self.tableWidget.item(4, 1)
item.setText(_translate("MainWindow", "5"))
item = self.tableWidget.item(4, 2)
item.setText(_translate("MainWindow", "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_())
【讨论】:
谢谢@Elan,但我认为这个问题与排序无关。我在原始代码中设置了 setSortingEnabled()。以上是关于从 PyQt 中的表格小部件中选择多行后,单元格小部件(按钮)显示在错误的位置的主要内容,如果未能解决你的问题,请参考以下文章
PyQt5 - 在表格小部件的列中创建一个检查项,即使行数与旋转框不同
如何使 QTableWidget 内的单元格小部件的背景不可选?