Как выровнять примитивный флажок с центром заголовка столбца QHeaderView?

У меня есть обычай QTableView модель с кастомом QHeaderView чтобы отобразить флажок, используемый для выполнения функции «выбрать все» для содержимого таблицы.

В моем заголовке перегружен paintSection() функция, я успешно отображаю флажок, используемый для выбора всех с:

QStyleOptionButton option;
option.rect = QRect(3,10,16,16);
option.state = QStyle::State_Enabled | QStyle::State_Active;
if (isChecked_)
option.state |= QStyle::State_On;
else
option.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);

К сожалению, флажок не отображается по центру, а вместо этого выравнивается по левому краю Это полностью противоречит правильно центрированному QStyledItemDelegate флажки в столбце для каждой записи таблицы.

Я знаю, что могу изменить первые два аргумента QRect изменить происхождение нарисованного примитива, но это не реагирует на изменения ширины столбца. Хотя фиксированная ширина столбца не является худшим решением.

Как правильно расположить флажок в заголовке столбца?

Вспомогательный вопрос: флажок в заголовке можно переключать, нажимая в любом месте в ячейке, а не только на самой коробке (в отличие от тех, которые представлены в таблице через делегатов). Есть ли способ это исправить?

2

Решение

Решение @scopchanov у меня не работает, так как флажок охватывает весь элемент заголовка

введите описание изображения здесь
введите описание изображения здесь

Возможное решение — нарисовать CheckBox со стилями, но помимо этого вы должны хранить память о том, проверен ли элемент или нет, для этого мы используем QMap<>первым элементом является logicalIndex поскольку он не изменяется даже при перемещении столбцов, а вторым элементом является состояние.

#include <QApplication>
#include <QHeaderView>
#include <QMouseEvent>
#include <QPainter>
#include <QStandardItemModel>
#include <QTableView>

class CheckedHeaderView : public QHeaderView
{
Q_OBJECT
public:
using QHeaderView::QHeaderView;
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
QStyleOptionButton opt;

QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt);
checkbox_rect.moveCenter(rect.center());
opt.rect = checkbox_rect;
opt.state = QStyle::State_Enabled | QStyle::State_Active;
if(logicalIndex == columnDown)
opt.state |= QStyle::State_Sunken;
if (states[logicalIndex])
opt.state |= QStyle::State_On;
else
opt.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, painter);
}
void mousePressEvent(QMouseEvent *event) override
{
QHeaderView::mousePressEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
columnDown = li;
updateSection(li);
}
void mouseReleaseEvent(QMouseEvent *event) override
{
QHeaderView::mouseReleaseEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
states[li] = !states[li];
Q_EMIT checked(li, states[li]);
columnDown = -1;
updateSection(li);
}
Q_SIGNALS:
void checked(int logicalIndex, bool state);
private:
QMap<int, bool> states;
int columnDown = -1;
};

class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget *parent = nullptr):
QTableView(parent)
{
CheckedHeaderView *header = new CheckedHeaderView(Qt::Horizontal, this);
setHorizontalHeader(header);
connect(header, &CheckedHeaderView::checked, this, &TableView::on_checked);
}
private Q_SLOTS:
void on_checked(int logicalIndex, bool state){
QItemSelectionModel::SelectionFlags command = state? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
for(int r=0; r < model()->rowCount(); r++){
QModelIndex ix = model()->index(r, logicalIndex);
selectionModel()->select(ix, command);
}
}
};int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TableView w;
QStandardItemModel *model = new QStandardItemModel(8, 6, &w);
w.setModel(model);
w.show();
return a.exec();
}

введите описание изображения здесь

2

Другие решения

QHeaderView::paintSection занимает QRect &rect в качестве аргумента. Задавать QStyleOption::rect быть равным rectто есть заменить

option.rect = QRect(3,10,16,16);

с

option.rect = rect;

Замечания: Это решение реагирует на изменения ширины столбца.

Используя вашу реализацию paintSection Я создал минимальный пример, чтобы продемонстрировать, как предлагаемое решение может быть реализовано. Код доступен на GitHub.

Приведенный пример дает следующий результат в Windows 7:

Windows 7 - окно с флажком в заголовке таблицы из трех строк

Результат на Windows 10:

Windows 10 - окно с флажком в заголовке таблицы из трех строк

Замечания: Это решение не работает в Linux, так как дает следующий результат (Ubuntu 17):

Ubuntu 17 - окно с флажком в заголовке таблицы из трех строк

0

По вопросам рекламы [email protected]