You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:52:10