我想从QTableWidget单元格内的QCheckBox获取一个状态。我已经为这个问题制作了示例代码。
import sys
from PyQt5.QtCore import Qt, QSettings
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtWidgets import QPushButton, QTableWidget, QCheckBox, QTextEdit
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setMinimumHeight(255)
self.tbl.setMaximumHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
chk_box = QCheckBox()
chk_box.setCheckState(Qt.Unchecked)
cell = QWidget()
hlayout = QHBoxLayout()
hlayout.addWidget(chk_box)
hlayout.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
cell.setLayout(hlayout)
self.tbl.setCellWidget(row, 0, cell)
vlayout = QVBoxLayout()
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.setLayout(vlayout)
self.show()
def get_data(self):
self.log.clear()
self.log.append(self.tbl.cellWidget(0, 0).isChecked())
self.log.append(self.tbl.cellWidget(0, 1).text())
self.log.append(self.tbl.cellWidget(0, 2).text())
if __name__ == "__main__":
APP = QApplication(sys.argv)
ex = TestUI()
sys.exit(APP.exec_())
我该怎么做?我无法通过此代码获取状态。
我认为代码应该是self.log.append(self.tbl.cellWidget(0, 0).????.isChecked())
。
但我不知道该怎么做
请帮帮我。
如果分析了将小部件放在第0列的代码:
chk_box = QCheckBox()
chk_box.setCheckState(Qt.Unchecked)
cell = QWidget()
hlayout = QHBoxLayout()
hlayout.addWidget(chk_box)
hlayout.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
cell.setLayout(hlayout)
self.tbl.setCellWidget(row, 0, cell)
需要注意的是,小部件集不是QCheckBox,而是QWidget,而QCheckBox是QWidget的儿子,因此可以使用findChild((方法获取信息。另一方面,item方法可能返回None,因此您应该检查它是否返回,因为它可能引发异常:
def get_data(self):
self.log.clear()
widget = self.tbl.cellWidget(0, 0)
if widget is not None:
chk_box = widget.findChild(QCheckBox)
if chk_box is not None:
self.log.append(str(chk_box.isChecked()))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
上面的一个更优雅的版本是使"单元格"成为一个自定义小部件,它公开了QCheckBox:的isChecked((方法
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.chk_box = QCheckBox()
self.chk_box.setCheckState(Qt.Unchecked)
hlayout = QHBoxLayout(self)
hlayout.addWidget(self.chk_box)
hlayout.setAlignment(Qt.AlignCenter)
hlayout.setContentsMargins(0, 0, 0, 0)
def isChecked(self):
return self.chk_box.isChecked()
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setMinimumHeight(255)
self.tbl.setMaximumHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
cell = Widget()
self.tbl.setCellWidget(row, 0, cell)
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.show()
def get_data(self):
self.log.clear()
widget = self.tbl.cellWidget(0, 0)
if widget is not None:
self.log.append(str(widget.isChecked()))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
可以推断,您使用QWidget将QCheckBox居中放置在单元格内,但我认为可以对其进行优化,以避免使用QProxyStyle创建小部件,然后通过QTableWidgetItem的checkState((方法访问信息:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QWidget,
QHBoxLayout,
QVBoxLayout,
QPushButton,
QTableWidget,
QTextEdit,
QTableWidgetItem,
QProxyStyle,
QStyle,
)
class ProxyStyle(QProxyStyle):
def subElementRect(self, element, option, widget):
r = super().subElementRect(element, option, widget)
if element == QStyle.SE_ItemViewItemCheckIndicator:
r.moveCenter(option.rect.center())
return r
class TestUI(QWidget):
def __init__(self):
super().__init__()
self.btn = QPushButton("Get Data")
self.tbl = QTableWidget()
self.log = QTextEdit()
self.init_ui()
def init_ui(self):
self.btn.clicked.connect(self.get_data)
proxy = ProxyStyle()
self.tbl.setStyle(proxy)
self.tbl.setFocusPolicy(Qt.NoFocus)
self.tbl.setFixedHeight(255)
self.tbl.setRowCount(20)
self.tbl.setColumnCount(3)
self.tbl.horizontalHeader().setStretchLastSection(True)
self.tbl.setHorizontalHeaderLabels(["", "Option", "Value"])
self.tbl.resizeRowsToContents()
self.tbl.resizeColumnsToContents()
for row in range(20):
it = QTableWidgetItem()
it.setCheckState(Qt.Checked)
self.tbl.setItem(row, 0, it)
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.btn)
vlayout.addWidget(self.tbl)
vlayout.addWidget(self.log)
self.show()
def get_data(self):
self.log.clear()
it0 = self.tbl.item(0, 0)
self.log.append(str(it0.checkState() == Qt.Checked))
it1 = self.tbl.item(0, 1)
self.log.append(it1.text() if it1 is not None else "")
it2 = self.tbl.item(0, 2)
self.log.append(it2.text() if it2 is not None else "")
if __name__ == "__main__":
APP = QApplication(sys.argv)
ex = TestUI()
sys.exit(APP.exec_())