Update: This issue is caused by a Qt bug. They solved it, for release in Qt 6.9.
https://bugreports.qt.io/browse/QTBUG-129290
Original Post: We had to port code to Qt6, and one of the things that broke was the QTableView
.
It is definitely an improvement - but I don't know how to fix the overlapping of text, hidden under the indicator. The only options that are easy are also bad:
QHeaderView::section:horizontal:first, QHeaderView::section:horizontal:only-one
which I had trouble figuring out for the subsequent columns).This is a super simple example showing the behavior, if somebody can help me until Qt fixes it completely. It behaves the same as the real program, the images cover the text.
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();
}
Thalia, among several options, I liked this very simple one.
#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QStyle>
#include <QItemDelegate>
#include <QPainter>
class Delegate : public QItemDelegate
{
private:
QPixmap checkedPix, uncheckedPix;
public:
Delegate(QObject *parent = nullptr):QItemDelegate(parent){
checkedPix=qApp->style()->standardPixmap(QStyle::SP_DialogApplyButton);
uncheckedPix=qApp->style()->standardPixmap(QStyle::SP_DialogCancelButton);
}
void drawCheck(QPainter *painter,
const QStyleOptionViewItem &option,
const QRect &rect,
Qt::CheckState state) const{
painter->drawPixmap(rect, state==Qt::Unchecked ? uncheckedPix:checkedPix);
}
/* you can also use: */
// void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const{
// cell pixmap
// }
// void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const{
// cell text
// }
// void drawBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{
// cell background
// }
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView tableView;
QStandardItemModel myModel;
tableView.setModel(&myModel);
myModel.setRowCount(5);
myModel.setColumnCount(1);
tableView.setStyleSheet(" QTableView::indicator { width: 30px; height: 30px; }");
tableView.setItemDelegateForColumn(0, new Delegate);//setItemDelegate, setItemDelegateForRow
for(int row=0; row<myModel.rowCount(); row++){
auto item=new QStandardItem("item");
item->setCheckable(true);
item->setCheckState(row%2==0 ? Qt::Checked : Qt::Unchecked);
myModel.setItem(row, 0, item);
}
tableView.show();
return a.exec();
}