QCheckBox в качестве делегата QTableView

Delegate, qcheckbox, qcheckbox center, QTableView

Доброго времени суток.
Возникла необходимость использовать делегат для отображения QCheckBox в таблице (выбирать объекты из списка для последующей работы с ними).
Для того чтобы разобратся с делегатами создал небольшой проект.
На выходе получаем следующее:

Структура проекта:

checkboxdelegate.h

#ifndef CHECKBOXDELEGATE_H
#define CHECKBOXDELEGATE_H
#include <QStyledItemDelegate>


class CheckBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    CheckBoxDelegate(QObject *parent = nullptr);

    // QAbstractItemDelegate interface
public:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

#endif // CHECKBOXDELEGATE_H

checkboxdelegate.cpp

#include "checkboxdelegate.h"
#include <QCheckBox>
#include <QApplication>

CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
    :QStyledItemDelegate (parent)
{

}

QWidget *CheckBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option)
    Q_UNUSED(index)

    //Cоздаем checkbox editor
    QCheckBox *editor = new QCheckBox(parent);
    return editor;
}

void CheckBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    //Установливаем выбрано/не выбрано
    QCheckBox *cb = qobject_cast<QCheckBox *>(editor);
    cb->setChecked(index.data().toBool());
}

void CheckBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    //Записываем данные в модель
    QCheckBox *cb = static_cast<QCheckBox *>(editor);
    int value = (cb->checkState()==Qt::Checked)? 1 : 0;
    model->setData(index, value, Qt::EditRole);
}

void CheckBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(index);
    QStyleOptionButton checkboxstyle;
    QRect checkbox_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);

    //Центрирование
    checkboxstyle.rect = option.rect;
    checkboxstyle.rect.setLeft(option.rect.x() +
                               option.rect.width()/2 - checkbox_rect.width()/2);

    editor->setGeometry(checkboxstyle.rect);
}


void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //Получаем данные
    bool data = index.model()->data(index, Qt::DisplayRole).toBool();

    //Создаем стиль CheckBox
    QStyleOptionButton checkboxstyle;
    QRect checkbox_rect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkboxstyle);

    //Центрирование
    checkboxstyle.rect = option.rect;
    checkboxstyle.rect.setLeft(option.rect.x() +
                               option.rect.width()/2 - checkbox_rect.width()/2);
    //Выбрано или не выбрано
    if(data)
        checkboxstyle.state = QStyle::State_On|QStyle::State_Enabled;
    else
        checkboxstyle.state = QStyle::State_Off|QStyle::State_Enabled;

    //Готово! Отображаем!
    QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkboxstyle, painter);
}

main.cpp

#include "checkboxdelegate.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QHeaderView>
#include <QTableView>

#define MODEL_ROWS 4            //Количество строк модели
#define MODEL_COLUMN 2          //Количество столбцов модели
#define DELEGATE_COLUMN 0       //Столбец с делегатом

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    //Создаем модель и представление
    QStandardItemModel *model = new QStandardItemModel(MODEL_ROWS, MODEL_COLUMN);
    QTableView *tableView = new QTableView();
    CheckBoxDelegate *delegate = new CheckBoxDelegate();

    //Заолняем модель данными
    for (int row =0; row < MODEL_ROWS; ++row) {
        for (int column = 0; column < MODEL_COLUMN; ++column) {
            QModelIndex index = model->index(row, column, QModelIndex());
            if(column == 0)
                model->setData(index, QVariant(0));
            else
                model->setData(index, QVariant((row + 1) * (column + 1)));
        }

    }
    //Устанавливаем модель в представление
    tableView->setModel(model);
    //Устанавливаем делегат в столбец
    tableView->setItemDelegateForColumn(DELEGATE_COLUMN, delegate);
    //Внешний вид предтавления
    tableView->resizeColumnsToContents();
    tableView->verticalHeader()->hide();
    tableView->horizontalHeader()->setStretchLastSection(true);

    tableView->setWindowTitle("Check Box Delegate");
    tableView->show();

    return a.exec();
}

Файл проекта:

CheckBoxDelegate_PG92889.7z CheckBoxDelegate_PG92889.7z

Единственная проблема состоит в том, что для выделения QCheckBox приходится дважны нажимать мышь. Получается что сначала выделяется ячейка. а только потом фокус уже попадает на виджет.

Виртуальный хостинг со скидкой 10 процентов
Виртуальный хостинг со скидкой 10 процентов
EVILEG предлагает надёжный хостинг со скидкой 10% на виртуальный хостинг и 5% на VPS
D
  • #
  • 11 августа 2019 г. 19:50

Пример лучше скину после отпуска.

Было бы интересно.

Если это будет достаточно самостоятельный код, то вы бы тогда могли написать небольшую статью на эту тематику в раздел Qt.

D
  • #
  • 17 августа 2019 г. 9:04
  • (ред.)

github ChekableTView

Правой групповая смена значения при перетаскивании левой как обычно.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Ищу работу?
14,000.00 руб. - 40,000.00 руб.
Разработчик Qt
Annino, Moscow Oblast, Russia
5,000.00 руб. - 15,000.00 руб.
Дизайнер
Moskovskiy, Moscow, Russia
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

А
22 августа 2019 г. 23:24
Александр73

Qt - Тест 001. Сигналы и слоты

  • Результат:47баллов,
  • Очки рейтинга-6
21 августа 2019 г. 10:23
Андрей Ермошин

C++ - Тест 002. Константы

  • Результат:58баллов,
  • Очки рейтинга-2
21 августа 2019 г. 10:15
Андрей Ермошин

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
19 августа 2019 г. 7:41
Андрей Янкович

это проблема дистрибутива, попробуйте установить через пакетный менеджер snap Суть проблемы: libQt5Core которая лежит в дистрибутиве требует версию glibc >= 2.25 у вас видимо …
b
18 августа 2019 г. 6:09
bbb116

cqtdeployer /home/aleks/CQtDeployer/bin/cqtdeployer: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by /home/aleks/CQtDeployer/lib/libQt5Core.so.5) linux mint …
D
17 августа 2019 г. 9:04
Damir

github ChekableTView Правой групповая смена значения при перетаскивании левой как обычно.
Сейчас обсуждают на форуме
24 августа 2019 г. 7:21
Евгений Легоцкой

Не помню, давно уже с QML не работал, по-моему, обычно пишет в консоль, что не находит файл. В любом случае какую-то ошибку в консоль выкидывает. Но если честно, если у вас проект будет ак…
БГ
24 августа 2019 г. 4:27
Брюс Глифф

Спасибо, вначале в документации было не понятно что к чему, теперь разобрался
I
21 августа 2019 г. 8:36
Intruder

Александр, мне не нужно перебирать. Вы говорите правильно, сначала я написал избыточный код просто не подумав. Задача такая, мне нужно просто переложить из QMap в атрибуты xml тега все, что там …
21 августа 2019 г. 4:46
IscanderChe

Спасибо! Получилось.
21 августа 2019 г. 3:16
nayk1982

Если Вы разрабатываете какую-то универсальную утилиту, которая вообще не привязана к логике, тогда как вариант: 1. Получить список таблиц через QSqlDatabase::tables 2. Для каждой табли…
EVILEG
О нас
Услуги
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB