IscanderChe
22 января 2019 г. 19:45

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

Qt, QSqlTableModel, QTableView

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

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

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

  1. class CheckBoxDelegate : public QStyledItemDelegate
  2. {
  3. Q_OBJECT
  4.  
  5. public:
  6. CheckBoxDelegate(QObject* parent = 0);
  7.  
  8. QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option,
  9. const QModelIndex& index) const override;
  10.  
  11. void setEditorData(QWidget* editor, const QModelIndex& index) const override;
  12. void setModelData(QWidget *editor, QAbstractItemModel *model,
  13. const QModelIndex &index) const override;
  14.  
  15. void updateEditorGeometry(QWidget *editor,
  16. const QStyleOptionViewItem &option, const QModelIndex &index) const override;
  17. };
  1. QWidget* CheckBoxDelegate::createEditor(QWidget* parent,
  2. const QStyleOptionViewItem& option,
  3. const QModelIndex& index) const
  4. {
  5. if(index.column() == 1)
  6. {
  7. QCheckBox* editor = new QCheckBox(parent);
  8. return editor;
  9. }
  10.  
  11. return QStyledItemDelegate::createEditor(parent, option, index);
  12. }
  13.  
  14. void CheckBoxDelegate::setEditorData(QWidget* editor,
  15. const QModelIndex& index) const
  16. {
  17. if(index.column() == 1)
  18. {
  19. int value = index.model()->data(index, Qt::EditRole).toBool();
  20. QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
  21. checkBox->setChecked(value != 0);
  22. }
  23. }
  24.  
  25. void CheckBoxDelegate::setModelData(QWidget* editor,
  26. QAbstractItemModel* model, const QModelIndex& index) const
  27. {
  28. if(index.column() == 1)
  29. {
  30. QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
  31. bool value = checkBox->isChecked();
  32. model->setData(index, value, Qt::EditRole);
  33. }
  34. }
  35.  
  36. void CheckBoxDelegate::updateEditorGeometry(QWidget* editor,
  37. const QStyleOptionViewItem& option, const QModelIndex& index) const
  38. {
  39. editor->setGeometry(option.rect);
  40. }
3

Вам это нравится? Поделитесь в социальных сетях!

9
Evgenii Legotckoi
  • 24 января 2019 г. 2:44
  • (ред.)

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

    IscanderChe
    • 16 февраля 2019 г. 3:22

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

      Evgenii Legotckoi
      • 17 февраля 2019 г. 23:28

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

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

      1. void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
      2. {
      3. if (index.column() == 1)
      4. {
      5. painter->save();
      6. bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
      7.  
      8. QStyleOptionButton check_box_style_option;
      9. check_box_style_option.state |= QStyle::State_Enabled;
      10. if (checked) {
      11. check_box_style_option.state |= QStyle::State_On;
      12. } else {
      13. check_box_style_option.state |= QStyle::State_Off;
      14. }
      15. check_box_style_option.rect = option.rect;
      16.  
      17. QApplication::style()->drawControl(QStyle::CE_CheckBox, &check_box_style_option, painter);
      18. painter->restore();
      19. return;
      20. }
      21.  
      22. QStyledItemDelegate::paint(painter, option, index);
      23. }
        IscanderChe
        • 19 февраля 2019 г. 12:51

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

          Evgenii Legotckoi
          • 19 февраля 2019 г. 14:34

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

          1. yourView->setEditTriggers(QAbstractItemView::AllEditTriggers)
            IscanderChe
            • 19 февраля 2019 г. 18:03

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

              Evgenii Legotckoi
              • 20 февраля 2019 г. 20:40

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

                IscanderChe
                • 20 июня 2019 г. 15:30

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

                  IscanderChe
                  • 21 июня 2019 г. 13:17

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

                    Комментарии

                    Только авторизованные пользователи могут публиковать комментарии.
                    Пожалуйста, авторизуйтесь или зарегистрируйтесь
                    • Последние комментарии
                    • IscanderChe
                      12 апреля 2025 г. 17:12
                      Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
                    • AK
                      1 апреля 2025 г. 11:41
                      Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
                    • Evgenii Legotckoi
                      9 марта 2025 г. 21:02
                      К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
                    • VP
                      9 марта 2025 г. 16:14
                      Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
                    • ИМ
                      22 ноября 2024 г. 21:51
                      Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…