从 QTableWidget 单元格中的 QCheckBox 获取状态
Get state from QCheckBox inside QTableWidget cell
我想从 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)
注意,widget集合不是QCheckBox而是一个QWidget,QCheckBox是QWidget的儿子,所以可以通过findChild()方法获取信息。另一方面,item 方法可能 return 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 "")
上面的一个更优雅的版本是使 "cell" 成为一个公开 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_())
我想从 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)
注意,widget集合不是QCheckBox而是一个QWidget,QCheckBox是QWidget的儿子,所以可以通过findChild()方法获取信息。另一方面,item 方法可能 return 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 "")
上面的一个更优雅的版本是使 "cell" 成为一个公开 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_())