Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting
TIMEWEB

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 приходится дважны нажимать мышь. Получается что сначала выделяется ячейка. а только потом фокус уже попадает на виджет.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
AA
April 17, 2019, 7:40 p.m.
Anton Ablin

Qt - Test 001. Signals and slots

  • Result:73points,
  • Rating points1
E
April 17, 2019, 6:16 p.m.
Evgeny

Qt - Test 001. Signals and slots

  • Result:100points,
  • Rating points10
E
April 17, 2019, 6:14 p.m.
Evgeny

Qt - Test 001. Signals and slots

  • Result:78points,
  • Rating points2
Last comments
U
April 18, 2019, 3:37 p.m.
Unreal_man

А как иконку в хедер задать?
u
April 18, 2019, 2:15 a.m.
uaa

доброго времени,большое спасибо за пример для начинающего)при адаптации к своему проекту столкнулся с таким ньансом:в vepolyline.h в 47 строке нужна инициализация по умолчанию: int m_pointF...
E
April 11, 2019, 12:49 p.m.
Evgeny

Спасибо за ответ) У меня компоновщик на нее ругался просто. Оказалось, просто забыл Q_OBJECT в начале класса указать.
April 11, 2019, 12:29 p.m.
Евгений Легоцкой

Добрый день. Вы имели ввиду реализацию? Для сигналов в Qt реализация не пишется, это всё генерируется в moc файлах под капотом Qt.
E
April 11, 2019, 12:15 p.m.
Evgeny

Здравствуйте. А где описание функции signal1()?
Now discuss on the forum
R
April 19, 2019, 9:55 a.m.
RED_Spider

мені важко це зараз навіть перевірити, тому що знайшов коміт, це ще було в 2016 році, і цей код не буде працювати коректно зараз, єдине скажу що це були QThread
i
April 17, 2019, 3:03 p.m.
ilya.guzikov

BlinCT, на стороне ++ это делать необходимо так как в qml при использовании функции append происходит перерисовка всех точек лини(как я понимаю) и из-за этого при использовании больших массиво...
April 10, 2019, 11:20 a.m.
Алексей Внуков

может тоже кому надо будет - QML не принимает QVector<QVector<int>> , при попытке вывести полученый вектор QML показывает что это QVariant(QVector<QVector<int> ...
SN
April 10, 2019, 9:36 a.m.
Stanislav Nykytiuk

Как реализовать такое меню, что бы нажмаешь меню подменю и выбор позиции? Данные меню и подменю в базе SQL.
Join us in social networks

For registered users on the site there is a minimum amount of advertising