Jan. 22, 2019, 7:45 a.m.

QSqlTableModel + QTableView + кастомный делегат в виде чекбокса

Qt, QSqlTableModel, QTableView

Всем добрый день.

Суть задачи: надо, чтобы в одной из колонок QTableView вместо хранимого в QSqlTableModel значения выводился чекбокс и при смене состояния чекбокса значения в базе тоже менялось. С помощью ItemIsUserCheckable проблему удалось решить.

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

class CheckBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    CheckBoxDelegate(QObject* parent = 0);

    QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
                          const QModelIndex& index) const override;

    void setEditorData(QWidget* editor, const QModelIndex& index) const override;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const override;

    void updateEditorGeometry(QWidget *editor,
            const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
QWidget* CheckBoxDelegate::createEditor(QWidget* parent,
    const QStyleOptionViewItem& option,
    const QModelIndex& index) const
{
    if(index.column() == 1)
    {
        QCheckBox* editor = new QCheckBox(parent);
        return editor;
    }

    return QStyledItemDelegate::createEditor(parent, option, index);
}

void CheckBoxDelegate::setEditorData(QWidget* editor,
    const QModelIndex& index) const
{
    if(index.column() == 1)
    {
        int value = index.model()->data(index, Qt::EditRole).toBool();
        QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
        checkBox->setChecked(value != 0);
    }
}

void CheckBoxDelegate::setModelData(QWidget* editor,
    QAbstractItemModel* model, const QModelIndex& index) const
{
    if(index.column() == 1)
    {
        QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
        bool value = checkBox->isChecked();
        model->setData(index, value, Qt::EditRole);
    }
}

void CheckBoxDelegate::updateEditorGeometry(QWidget* editor,
    const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    editor->setGeometry(option.rect);
}
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.
9

Добрый день! Про ваш вопрос помню, вынужден немного отложить, работы много. Чуть позже гляну кое-какие рабочие исходники с делегатами, нечто подобное уже реализовывал.

Доброй ночи. Скромно напоминаю о своём вопросе...

Добрый день. Очень извиняюсь за долгий ответ

Первое, что нашёл, так это необходимость перерисовать чекбокс.

void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (index.column() == 1)
    {
        painter->save();
        bool checked = index.model()->data(index, Qt::DisplayRole).toBool();

        QStyleOptionButton check_box_style_option;
        check_box_style_option.state |= QStyle::State_Enabled;
        if (checked) {
            check_box_style_option.state |= QStyle::State_On;
        } else {
            check_box_style_option.state |= QStyle::State_Off;
        }
        check_box_style_option.rect = option.rect;

        QApplication::style()->drawControl(QStyle::CE_CheckBox, &check_box_style_option, painter);
        painter->restore();
        return;
    }

    QStyledItemDelegate::paint(painter, option, index);
}

Да, теперь чекбокс виден постоянно. Но для того, чтобы изменить его состояние, прежде нужно выделить ячейку с ним. Это как-то лечится?

Попробуйте включить все триггеры редактирования

yourView->setEditTriggers(QAbstractItemView::AllEditTriggers)

Тот же эффект.

Думаю, что ещё можно переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, который содержит модель и немного поиграться с индексом. Если это индекс, который соответствует колонке с чекбоксом, то изменить значение принудительно не дожидаясь перехода ячейки в режим редактирования.

Вернулся к этой задачке только-только, поэтому и не ответил ничего раньше. Как переопределить mouseReleaseEvent(QMouseEvent* event) у QTableView, если QTableView задан в ui? Или задавать QTableView только через код?

Всё, с этим разобрался.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting Timeweb
g
May 29, 2020, 2:32 p.m.
glushchenkoin

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:40points,
  • Rating points-8
AS
May 26, 2020, 11:29 a.m.
Artem Sun-Dun-Chan

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
MN
May 25, 2020, 11:33 a.m.
Mitja Nagibin

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
Last comments
May 29, 2020, 1 p.m.
Evgenij Legotskoj

Django - Tutorial 023. Like Dislike system using GenericForeignKey

Думал так, но похоже что нет. {{ post.votes.likes.user.username }} Это же QuerySet будет, а не отдельный единственный объект {% for vote in post.votes %} {{ vote.user.username …
May 29, 2020, 11:43 a.m.
Vladislav Melenchuk

Django - Tutorial 023. Like Dislike system using GenericForeignKey

А как получить имя пользователя, который поставил лайк? Думал так, но похоже что нет. {{ post.votes.likes.user.username }}
May 29, 2020, 6:30 a.m.
Evgenij Legotskoj

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

У меня работает. Исправлял в проекте, который приложен к статье. А что происходит в вашем коде, с учётом места вызова этого кода, я знать не могу ;) Дебажьте и добавляйте условия, кото…
MA
May 29, 2020, 6:27 a.m.
Mihail A

Qt/C++ - Lesson 039. How to paint stroke in QSqlTableModel by value in the column?

QModelIndexList rowIndexes = ui->tableView->selectionModel()->selectedRows(); model->removeRows(rowIndexes.first().row(), rowIndexes.size()); model-&…
Now discuss on the forum
May 31, 2020, 6:57 a.m.
Aleksej Vnukov

Минимальный размер Item

считайте по размеру включенных элементов, чтоб все помещалась. например у вас всего 2 кнопки, тогда минимальный размер итема будет ширина 1-й кнопки + ширина 2-й кнопки + отступы, и точно также …
f
May 31, 2020, 2:24 a.m.
fryn3

Можно ли сделать в QML таблицу как в Excel?

Можно ли сделать в QML таблицу как в Excel или как сделано в QTableView? Что бы можно было выделять диапазон ячеек, переключатся по таб, изменять размеры строк и столбцов. В QT 5.14 по…
S
RS
May 30, 2020, 11:49 a.m.
Ruslan Skljuev

QML Как при нажатии на кнопку изменить название окна?

У меня три файла: 1. QML - это Loader и Window 2. QML вход в программу - страница Loader (там есть Switch) 3. QML - MainMenu. Мне нужно в (1), чтобы если на (2) Switch.enable, то …
DK
May 29, 2020, 1:27 p.m.
Dzhon Kofi

QMap<> какой ключ лучше

это ясно. Вопрос в том, как быстро мапа будет отрабатывать, если ключом будет QModelIndex. Какой параметр индекса возьмет за ключ. И вот насколько это будет медленнее или быстрее, чем QString пр…
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB