QSqlTableModel + QTableView + кастомный делегат QComboBox
Пытаюсь реализовать кастомного делегата на основе QComboBox. Получилось отчасти.
1) При щелчке на ячейке в колонке с делегатом (у меня это колонка 4, status) комбобокс появляется, а хотелось бы, чтобы он был виден всегда.
2) При загрузке виджета, если строк в таблице несколько, только в последней строке заполнена колонка status. Надо, чтоб показывались все.
3) Если щелкнуть на ячейке колонки status, где установлено значение "green", а потом перейти на другую ячейку, то значение предыдущей ячейки сбрасывается на значение "white". Должны сохраняться предыдущие установленные значения.
#include "comboboxdelegate.h" #include <QComboBox> ComboBoxDelegate::ComboBoxDelegate(QObject* parent) { } QWidget* ComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { if(index.column() == 4) { QComboBox* editor = new QComboBox(parent); editor->insertItem(0, "white"); editor->insertItem(1, "green"); return editor; } return QStyledItemDelegate::createEditor(parent, option, index); } void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { if(index.column() == 4) { QString value = index.model()->data(index, Qt::EditRole).toString(); QComboBox* comboBox = static_cast<QComboBox*>(editor); if(value == "white") comboBox->setCurrentIndex(0); else if(value == "green") comboBox->setCurrentIndex(1); } } void ComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { if(index.column() == 4) { QComboBox* comboBox = static_cast<QComboBox*>(editor); QString value = comboBox->currentData().toString(); model->setData(index, value, Qt::EditRole); } } void ComboBoxDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { editor->setGeometry(option.rect); }
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.Do you like it? Share on social networks!
- Максим Васильев
- Oct. 2, 2024, 4:14 a.m.
Qt - Test 001. Signals and slots
- Result:68points,
- Rating points-1
- Лев Семенов
- Sept. 30, 2024, 11:04 a.m.
C++ - Test 001. The first program and data types
- Result:53points,
- Rating points-4
- Андрей Андреев
- Sept. 27, 2024, 9:01 a.m.
C++ - Test 001. The first program and data types
- Result:60points,
- Rating points-1
Добрый день!
А можете ещё прикрепить какой-нибудь пробный проект с этим делегатом? Я бы вечером глянул после работы, что там, да как.
1) Насчёт того, чтобы делегат был виден всегда. Можете попробовать переопределить метод paint у делегата
Что-то наподобие такого, только перепишите в рамках вашего делегата.
2) Немного не понял
3) Не уверен, но возможно, что нужно поработать ещё немного с самой моделью данных.
По пункту 1 - да, всё получилось, спасибо. Я почти дошёл до этого, но переопределял paint не совсем правильно.
По пункту 2 - картинка в прицепе. Для первых двух комбобоксов значения менялись с их же помощью, для следующих двух значения предустановлены программно.
По пункту 3 - возможно, что надо задействовать модель, я только пока не понимаю, как. Сейчас у меня там кроме формата отображения дат больше ничего нет.
По пункту 3 попытался переписать метод setData. В итоге комбобокс перестал работать.
В общем, полностью переписал код, получилось вот что:
Всё работает как надо: выставляется значение по умолчанию white, сохраняются значения, выставленные ранее. Осталось только одно затруднение: доступ к комбобоксу осуществляется после двойного щелчка мыши. Хотелось бы с первого щелчка.
Попробуйте включить все триггеры редактирования у TableView, а потом уже немного поиграться с ними, если заработает.
Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком.
И выделяется первая ячейка для редактирования текста, что совсем не надо. Похоже, надо опять думать в сторону собственной реализации QTableView...
"Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком." Это осталось, а вот с редактированием удалось успешно закрыть вопрос. Добавилась собственная реализация QTableView и несколько строк в widget.cpp.
Огромное спасибо за помощь по работе с моделями! Трудновато, но очень интересно.)
С проблемой редактирования текста разобрался с помощью другого дружественного ресурса путём наследования модели и переписывания метода flags. Получилось более элегантно и без костылей в виде кастомного QTableView:
Но вылезла другая интересная проблема. Как удалось выяснить, при выборе другого значения в комбобоксе данные вносятся в базу данных только после щелчка на другой ячейке или свободном пространстве. Можно это как-то побороть, чтобы данные записывались сразу после выбора значения?
Я думаю, что нужно попробовать делегат переписать, чтобы он сразу отсылал сигнал об изменении данных, как только выбрано какое-то значение в комбобоксе. По сути, значение не подтверждается, пока нет перехода в другую ячейку.
Если напрямую из setEditorData делать так:
то компилятор выдаёт ошибку: "passing 'const ComboBoxDelegate' as 'this' argument discards qualifiers [-fpermissive]"
commitData ожидает неконстантный указатель на виджет, а у вас туда передаётся константный указатель.
В общем, мозг сломал, но так ничего и не придумал... Слишком тонкие намёки для меня.))
Вот если бы чуть более развёрнутое объяснение... И примеров кода не надо! Только объяснение.
А мне бы наоборот код глянуть )) Можете показать, где у вас emit commitData(editor) используется? А то я всё уже в голове не успеваю держать, детали из памяти истераются.
Придумал. Вот что попробуйте, сделайте в методе createEditor коннект лямбды на изменение текущего индекса. В котором и будете делать commitData.
По идее, когда вы измените значение, тогда сразу и вызовется применение изменений.
Спасибо, попробую завтра. На работе у меня стоит 5.11, там QOverload поддерживается. А вот дома стоит 5.5.1, и этого там ещё нет...
Не знаете, как правильно под 32-битный линукс скомпилить одновременно и QtCreator, и свежий Qt? Несколько надоело быть ограниченно годным в домашних условиях.
Ну я никогда не компилировал сам Qt, просто устанавливал нужные версии через Qt Maintanence Tool и всё. Этого достаточно было.
Вот ещё, кстати, вопрос не по теме. В сообщениях указывается время, отличное от моего местного. Это правильно? Особо не мешает, но вопрос есть. :) Хорошо бы настроить возможность определять/задавать часовой пояс в профиле пользователя.
Всё равно ругается: "passing 'const ComboBoxDelegate' as 'this' argument discards qualifiers [-fpermissive] emit commitData(comboBox);".
Да надо бы это сделать. Я столкнулся в Django с тем, что довольно трудоёмко реализовать автоматическую детекцию часового пояса. А в официальной документации сказано, что добавляйте у пользователя поле для настройки часового пояся и выбирайте из него данные. Ну наверное да, нужно сделать ))))
етить колотить. Не обратил внимание на то, что это тоже const метод. Попробуйте тогда написать обычный слот без лямбды и подключиться к нему.
Сигнал работает, сообщение "ComboBox index changed" появляется в момент смены значения, всё как надо. Только как теперь в модель всё это передать? Доступа-то к ней из слота нет.
Попробуйте так
Сработало! Спасибо!!!
Кстати, скорее всего на новом синтаксисе сигналов и слотов через указатели на методы не получится так сделать. Дело в том, что Макросы кладут болт на некоторые моменты в плане приватности и константности объектов... Но я бы проверил...
Можете проверить коннект так? Любопытства ради. Если я правильно понимаю, то тогда не сможет скомпилироваться...
Скомилировалось и нормально работает.
Хорошо, значит ошибочная мысль была. Спасибо.
Оставьте тогда на новом синтаксисе. Уже не комильфо использовать старый синтаксис )))
Добрый день.
Я тут жаловался в посте выше ( тут ), что: "Теперь со второго щелчка работает: вначале выделить ячейку, потом уже работать с выпадающим списком." Т.е. комбобокс в делегате начинал работать только после того, как щёлкнешь на нём: клик, и потом на второй клик уже список значений выпадает.
Удалось победить с помощью дружественного форума так:
где индекс указывает на те ячейки, где размещается делегат.
Круто, хорошо, что удалось разобраться :-)