python - QTableWidget 和 setCellWidget:调整大小问题
问题描述
我试图在 QTableWidget 的某个单元格中插入一些 QRadioButton。情况与本帖中的情况类似。特别是,@eyllanesc 的解决方案PySide2
如下
import sys
from PySide2.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, \
QButtonGroup, QRadioButton
app = QApplication(sys.argv)
searchView = QTableWidget(0, 4)
colsNames = ['A', 'B', 'C']
searchView.setHorizontalHeaderLabels(['DIR'] + colsNames)
dirNames = {'A': ['/tmp', '/tmp/dir1'], 'B': ['/tmp/dir2'],
'C': ['/tmp/dir3']}
rowCount = sum(len(v) for (name, v) in dirNames.items())
searchView.setRowCount(rowCount)
index = 0
for letter, paths in dirNames.items():
for path in paths:
it = QTableWidgetItem(path)
searchView.setItem(index, 0, it)
group = QButtonGroup(searchView)
for i, name in enumerate(colsNames):
button = QRadioButton()
group.addButton(button)
searchView.setCellWidget(index, i + 1, button)
if name == letter:
button.setChecked(True)
index += 1
searchView.show()
sys.exit(app.exec_())
在调整列或行的大小时,我注意到一个奇怪的行为:当我按下鼠标按钮并调整列或原始大小时,QRadioButtons 仍然在它们的位置,导致一些冲突;然后,当我最终松开鼠标按钮时,每个 QRadioButton 都会到位。有没有办法避免在调整大小的过程中使 QRadioButtons 也移动?
解决方案
由于我以前的解决方案会产生其他问题,因此在此解决方案中,我将展示另一种选择:
- 使用 Qt::CheckStateRole 通过委托实现排除逻辑。
- QProxyStyle 可用于绘画
import sys
from PySide2.QtCore import Qt, QEvent
from PySide2.QtWidgets import (
QApplication,
QTableWidget,
QTableWidgetItem,
QStyledItemDelegate,
QStyle,
QStyleOptionViewItem,
QProxyStyle,
)
class RadioButtonDelegate(QStyledItemDelegate):
def editorEvent(self, event, model, option, index):
flags = model.flags(index)
if (
not (flags & Qt.ItemIsUserCheckable)
or not (option.state & QStyle.State_Enabled)
or not (flags & Qt.ItemIsEnabled)
):
return False
state = index.data(Qt.CheckStateRole)
if state is None:
return False
widget = option.widget
style = widget.style() if widget is not None else QApplication.style()
# make sure that we have the right event type
if (
(event.type() == QEvent.MouseButtonRelease)
or (event.type() == QEvent.MouseButtonDblClick)
or (event.type() == QEvent.MouseButtonPress)
):
viewOpt = QStyleOptionViewItem(option)
self.initStyleOption(viewOpt, index)
checkRect = style.subElementRect(
QStyle.SE_ItemViewItemCheckIndicator, viewOpt, widget
)
me = event
if me.button() != Qt.LeftButton or not checkRect.contains(me.pos()):
return False
if (event.type() == QEvent.MouseButtonPress) or (
event.type() == QEvent.MouseButtonDblClick
):
return True
else:
return False
if state != Qt.Checked:
for c in range(model.columnCount()):
if c not in (0, index.column()):
ix = model.index(index.row(), c)
model.setData(ix, Qt.Unchecked, Qt.CheckStateRole)
return model.setData(index, Qt.Checked, Qt.CheckStateRole)
return False
class RadioStyle(QProxyStyle):
def drawPrimitive(self, element, option, painter, widget=None):
if element == QStyle.PE_IndicatorItemViewItemCheck:
element = QStyle.PE_IndicatorRadioButton
super().drawPrimitive(element, option, painter, widget)
app = QApplication(sys.argv)
searchView = QTableWidget(0, 4)
style = RadioStyle(searchView.style())
searchView.setStyle(style)
delegate = RadioButtonDelegate(searchView)
searchView.setItemDelegate(delegate)
colsNames = ["A", "B", "C"]
searchView.setHorizontalHeaderLabels(["DIR"] + colsNames)
dirNames = {"A": ["/tmp", "/tmp/dir1"], "B": ["/tmp/dir2"], "C": ["/tmp/dir3"]}
rowCount = sum(len(v) for (name, v) in dirNames.items())
searchView.setRowCount(rowCount)
index = 0
for letter, paths in dirNames.items():
for path in paths:
it = QTableWidgetItem(path)
searchView.setItem(index, 0, it)
for i, name in enumerate(colsNames):
it = QTableWidgetItem()
searchView.setItem(index, i + 1, it)
it.setCheckState(Qt.Checked if name == letter else Qt.Unchecked)
index += 1
searchView.show()
sys.exit(app.exec_())
推荐阅读
- python - Apache2 上的第二个 Flask 应用程序出现问题
- amazon-redshift - 从 Redshift 中的 sysdate 减去 5 小时
- fortran - 有效性 - 从未格式化的二进制文件读取时检查逻辑值
- vb.net - 未为类型“DBNull”和类型“DBNull”定义运算符“=”
- javascript - 为什么函数的原型必须是它的孩子?
- reactjs - 是否可以将 React.hook 传递给函数?
- php - Google API 服务器到服务器身份验证 PHP
- arrays - 如何根据多个值对数据数组进行分组?
- c# - 实体框架未将新创建的对象 ID 分配给子对象
- mysql - 从 mySQL 显示多个 Blob 文件