Qt6中QTableView样式表指示器与文本重叠问题(Qt6.9将修复)
更新说明
此问题为Qt已知Bug,官方已修复,将在Qt 6.9版本中发布,Bug编号:QTBUG-129290
原问题描述
代码迁移至Qt6后,QTableView的自定义复选框指示器出现样式异常,不同版本表现如下:
- Qt5.15及更早版本:带自定义复选框指示器的样式表可正常工作
- Qt6.5.3:自定义图片指示器与默认复选框、项文本重叠
- Qt6.6.3和6.7.2:默认指示器不再显示,但自定义指示器仍与文本重叠
尝试过添加空格、拆分列等临时方案,均存在弊端;目前通过条件编译禁用样式表,但无法保持桌面端与嵌入式端样式一致性,现附可复现代码,寻求临时解决办法。
可复现代码
main.cpp
#include "mymodel.h" #include <QApplication> #include <QTableView> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTableView tableView; MyModel myModel; tableView.setModel(&myModel); QString viewStyle = "QTableView::item { padding: 10px; }\n" "QTableView::indicator { width: 30px; height: 30px; }\n" "QTableView::indicator:unchecked { image: url(:/checkbox_unselected.png); }\n" "QTableView::indicator:checked { image: url(:/checkbox_selected.png); } "; tableView.setStyleSheet(viewStyle); tableView.setColumnWidth(0, 100); tableView.setColumnWidth(1, 100); tableView.setColumnWidth(2, 100); tableView.setRowHeight(0, 100); tableView.setRowHeight(1, 100); tableView.show(); return a.exec(); }
mymodel.h
#include <QAbstractTableModel> class MyModel : public QAbstractTableModel { public: explicit MyModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; };
mymodel.cpp
#include "mymodel.h" MyModel::MyModel(QObject *parent) : QAbstractTableModel(parent) { } int MyModel::rowCount(const QModelIndex & /*parent*/) const { return 2; } int MyModel::columnCount(const QModelIndex & /*parent*/) const { return 3; } QVariant MyModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { return QString("Row%1, Column%2").arg(index.row() + 1).arg(index.column() +1); } else if (role == Qt::CheckStateRole) { return (index.column() == 0) ? Qt::Checked : Qt::Unchecked; } return QVariant(); }
临时解决办法
方法1:自定义代理(QStyledItemDelegate)
通过重写paint方法,手动绘制复选框和文本,彻底规避样式表的布局冲突:
#include <QStyledItemDelegate> #include <QPainter> class CheckBoxDelegate : public QStyledItemDelegate { public: explicit CheckBoxDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { // 绘制自定义复选框 if (index.data(Qt::CheckStateRole).isValid()) { QRect checkRect(option.rect.left() + 5, option.rect.center().y() - 15, 30, 30); QString imgPath = (index.data(Qt::CheckStateRole).toInt() == Qt::Checked) ? ":/checkbox_selected.png" : ":/checkbox_unselected.png"; painter->drawPixmap(checkRect, QPixmap(imgPath)); } // 绘制文本,偏移位置避免重叠 QStyleOptionViewItem textOption = option; textOption.rect.setLeft(option.rect.left() + 40); // 预留复选框+间距的空间 QStyledItemDelegate::paint(painter, textOption, index); } };
使用代理:
// 在main.cpp中添加 CheckBoxDelegate *delegate = new CheckBoxDelegate(&tableView); tableView.setItemDelegate(delegate);
方法2:调整样式表的内边距与指示器定位
修改样式表,给文本预留足够空间,同时固定指示器位置:
QTableView::item { padding-left: 40px; /* 给30px的复选框+10px间距留足空间 */ padding-top: 10px; padding-bottom: 10px; padding-right: 10px; } QTableView::indicator { width: 30px; height: 30px; left: 5px; /* 固定左侧间距 */ top: 50%; transform: translateY(-50%); /* 垂直居中 */ } QTableView::indicator:unchecked { image: url(:/checkbox_unselected.png); } QTableView::indicator:checked { image: url(:/checkbox_selected.png); }
此方法无需修改业务代码,只需根据复选框尺寸调整padding-left和left的值即可。
内容的提问来源于stack exchange,提问作者Thalia
相关产品推荐
相关产品推荐

