python - 如何从 QComboBox 中获取所选项目以显示在 PyQt5 的 QTableWidget 中?(QComboBox 有复选框来选择项目)
问题描述
我有 QTableWidget,其中每一行都有特定列的 QComboBox。我的每个 QCombobox 都有多个带有复选框的值。我想在同一行的下一个相应列“SelectedMonths”中显示每个组合框中的选定项目,并在未选中时将其删除(反之亦然)。
到目前为止,我已经准备好脚本,它为我提供了所有已选中/未选中的项目,但我不知道如何获取激活组合框的行的索引。
获取工作流程的片段
示例代码:
QtDesigner 生成的代码:Demo.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(464, 291)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
self.tableWidget.setGeometry(QtCore.QRect(30, 30, 411, 221))
self.tableWidget.setRowCount(1)
self.tableWidget.setColumnCount(2)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(0, 0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setItem(0, 1, item)
self.tableWidget.horizontalHeader().setVisible(False)
self.tableWidget.verticalHeader().setVisible(False)
MainWindow.setCentralWidget(self.centralwidget)
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"))
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
item = self.tableWidget.item(0, 0)
item.setText(_translate("MainWindow", "Select Months"))
item = self.tableWidget.item(0, 1)
item.setText(_translate("MainWindow", "Selected Months"))
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_())
我写的代码:DemoCode.py
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QTableWidgetItem
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtCore import Qt
from datetime import date
from dateutil.relativedelta import relativedelta
from Demo import Ui_MainWindow
def CheckableCombobox(combo, options):
model = QStandardItemModel(len(options), 1)
firstItem = QtGui.QStandardItem("SelectMonths")
firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
firstItem.setSelectable(False)
model.setItem(0, 0, firstItem)
for i, area in enumerate(options):
item = QStandardItem(area)
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
item.setData(Qt.Unchecked, Qt.CheckStateRole)
model.setItem(i+1, 0, item)
combo.setModel(model)
class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(DemoCode, self).__init__()
self.setupUi(self)
self.rowPosition = self.tableWidget.rowCount()
for row in range(0,3):
self.tableWidget.insertRow(self.rowPosition)
for column in range(0,2):
if column == 0:
self.ComboBox = QtWidgets.QComboBox()
dtStart = date.today()
self.Monthlist = []
for n in range(1, 5):
self.Monthlist.append((dtStart + relativedelta(months=-n)).strftime('1-%b-%Y'))
CheckableCombobox(self.ComboBox, self.Monthlist)
self.ComboBox.model().itemChanged.connect(self.on_itemChanged)
self.tableWidget.setCellWidget(self.rowPosition, column, self.ComboBox)
elif column == 1:
item = QTableWidgetItem('')
self.tableWidget.setItem(self.rowPosition, column, item)
self.rowPosition += 1
self.tableWidget.setColumnWidth(1,150)
def on_itemChanged(self, item):
current_state = item.data(Qt.CheckStateRole)
print(current_state, item.text())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = DemoCode()
window.show()
sys.exit(app.exec_())
解决方案
您应该找到一种方法来跟踪每个组合模型的行,以便您可以相应地设置项目文本。
请注意,我稍微更改了您的代码逻辑,因为存在一些概念错误:
- 如果不需要,请不要设置实例属性:所有这些
self.rowPosition
,self.monthList
等,每次 for 循环循环时都会更改,之后您就不需要它们了; - 避免对变量和函数使用大写名称
- 月份列表始终相同,在 for 循环之前构建它,而不是每次都计算它
- 而不是将模型设置为函数中的组合,而是使其返回模型
编辑:评论请求后添加复制功能
def createModel(options):
model = QStandardItemModel(len(options), 1)
firstItem = QtGui.QStandardItem("SelectMonths")
firstItem.setBackground(QtGui.QBrush(QtGui.QColor(200, 200, 200)))
firstItem.setSelectable(False)
model.setItem(0, 0, firstItem)
for i, area in enumerate(options):
item = QStandardItem(area)
item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
item.setData(Qt.Unchecked, Qt.CheckStateRole)
model.setItem(i+1, 0, item)
return model
class DemoCode(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(DemoCode, self).__init__()
self.setupUi(self)
monthList = [(date.today() + relativedelta(months=-n)).strftime('1-%b-%Y') for n in range(1, 5)]
self.models = {}
rows = self.tableWidget.rowCount()
for row in range(rows, rows + 3):
self.tableWidget.insertRow(row)
comboBox = QtWidgets.QComboBox()
model = createModel(monthList)
comboBox.setModel(model)
model.itemChanged.connect(lambda _, row=row: self.on_itemChanged(row))
self.models[row] = model
self.tableWidget.setCellWidget(row, 0, comboBox)
item = QTableWidgetItem()
self.tableWidget.setItem(row, 1, item)
self.tableWidget.setColumnWidth(1,150)
def on_itemChanged(self, tableRow):
model = self.models[tableRow]
items = []
for row in range(model.rowCount()):
comboItem = model.index(row, 0)
if comboItem.data(Qt.CheckStateRole):
items.append(comboItem.data())
self.tableWidget.item(tableRow, 1).setText(', '.join(items))
def copyFromRow(self, tableRow):
sourceModel = self.models[tableRow]
checkedRows = []
for row in range(sourceModel.rowCount()):
if sourceModel.index(row, 0).data(Qt.CheckStateRole):
checkedRows.append(row)
for model in self.models.values():
if model == sourceModel:
continue
for row in range(model.rowCount()):
model.setData(
model.index(row, 0),
Qt.Checked if row in checkedRows else Qt.Unchecked,
Qt.CheckStateRole)
我还建议删除“Select Months”和“Selected Months”项目,并将它们用作表头。
推荐阅读
- c# - Microsoft.Data.SqlClient.SqlException:存在同名数据库,或无法打开指定文件,或位于 UNC 共享上
- python - Python - 枕头圆角矩形不起作用
- c++ - 如何找到具有重复数字的最小数字向量?
- android - 如何在android studio中做到这一点?
- vim - 搜索 cmd 和选项(如 flp)中使用的模式
- python - LinkedIn V2 API Marketing Developer Platform - 获取 ugcPost 参考 URN 的数据返回 500 错误
- postgresql - 现有数据集上的 Postgres 13 + pglogical 2.3.4
- python - plt.hist MatPlotlib 中的 bins 选项
- i2c - 读取 I2C 传感器时 Pi Pico 错误 EIO
- python - 合并 txt 文件问题,输出文件不是 txt