PyQt5 - 在表格小部件的列中创建一个检查项,即使行数与旋转框不同
Posted
技术标签:
【中文标题】PyQt5 - 在表格小部件的列中创建一个检查项,即使行数与旋转框不同【英文标题】:PyQt5 - Create a check item in a column of a table widget even with the number of rows varying from a spinbox 【发布时间】:2020-07-19 21:20:51 【问题描述】:我是 PyQt5 的新手,我正在使用 Qtdesigner 开发一个界面。
我正在从微调框中控制表格小部件的行数。但是,在更改行数时,我需要保留 a 列的检查选项。
我设法根据旋转框中的 valueChanged 更改了行数,但是我创建的用于创建检查的循环不管行数都不起作用。
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(519, 468)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.spinBox = QtWidgets.QSpinBox(self.centralwidget)
self.spinBox.setGeometry(QtCore.QRect(80, 131, 41, 31))
self.spinBox.setProperty("value", 2)
self.spinBox.setObjectName("spinBox")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(160, 80, 341, 101))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(2)
self.tableWidget.setRowCount(2)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsUserCheckable|QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(1, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(1, 1, item)
self.tableWidget.verticalHeader().setVisible(False)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 519, 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)
self.spinBox.valueChanged['int'].connect(self.tableWidget.setRowCount)
for i in range(self.tableWidget.rowCount()):
item = QtWidgets.QTableWidgetItem()
item.setFlags(QtCore.Qt.ItemIsEnabled)
item.setCheckState(QtCore.Qt.Checked)
self.tableWidget.setItem(i, 0, item)
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", "d"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "e"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "a"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "c"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
item = self.tableWidget.verticalHeaderItem(0)
item.setText(_translate("MainWindow", "d"))
item = self.tableWidget.verticalHeaderItem(1)
item.setText(_translate("MainWindow", "e"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "a"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "c"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
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_())
【问题讨论】:
我可以看到图片中的复选框。你能准确解释什么没有按预期工作吗? 你的意思是当你添加一个新行时它没有得到一个复选框? 【参考方案1】:首先,您似乎正在编辑pyuic
生成文件的输出,或者您正在尝试模仿它的行为。无论如何,这是永远不应该做的事情。
这些文件应该保持原样,您应该只将它们用作模块;要了解如何正确执行此操作,请阅读有关 using Designer 的更多信息。如果您试图模仿他们的行为,那么您不应该这样做:处理 pyuic 文件的方式仅被视为“解释层”,以便创建 GUI 对象并使其可以从 python 访问。如果您是从代码构建 GUI,只需将要使用的 QWidget 子类化(通常是 QWidget、QDialog 或 QMainWindow)。
现在,问题是每当setRowCount()
被调用...:
[it] 将此表模型中的行数设置为行。如果这小于 rowCount(),则不需要的行中的数据被丢弃。
这显然意味着,如果您要删除行,则会丢失该行中的所有项目(包括它们完全可以检查的事实)。
要正确更新内容并添加可检查的项目,您需要在动态删除或添加项目的特定方法中执行此操作。
在下一个示例中,我将展示如何正确实现这一点(并且以更简单、更清晰的方式):
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
self.setCentralWidget(central)
layout = QtWidgets.QHBoxLayout(central)
self.spin = QtWidgets.QSpinBox()
layout.addWidget(self.spin)
self.table = QtWidgets.QTableWidget(2, 2)
layout.addWidget(self.table)
self.table.verticalHeader().setVisible(False)
for col, label in enumerate(('a', 'c')):
header = QtWidgets.QTableWidgetItem(label)
self.table.setHorizontalHeaderItem(col, header)
if col:
continue
for row in range(self.table.rowCount()):
item = QtWidgets.QTableWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Checked)
self.table.setItem(row, col, item)
self.spin.setValue(self.table.rowCount())
self.spin.valueChanged.connect(self.setRowCount)
def setRowCount(self, count):
if count == self.table.rowCount():
return
# if there are too many rows, remove them
while self.table.rowCount() > count:
self.table.removeRow(self.table.rowCount() - 1)
# if rows are going to be added, create checkable items for them
while self.table.rowCount() < count:
row = self.table.rowCount()
self.table.insertRow(row)
item = QtWidgets.QTableWidgetItem()
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
item.setCheckState(QtCore.Qt.Checked)
self.table.setItem(row, 0, item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())
作为旁注,有几个注意事项:
布局管理器应始终用于小部件,否则内容可能会变得不可见或无法调整其位置; 您定义了retranslateUi
两次;我想这是编辑 pyuic 文件后留下的东西,但无论如何,重新定义具有相同名称的函数会导致覆盖它(除非它们每个都有唯一的装饰器)
【讨论】:
以上是关于PyQt5 - 在表格小部件的列中创建一个检查项,即使行数与旋转框不同的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PyQt5 Python 中更改表格小部件中滚动条的颜色