Russian Qt Forum
Май 23, 2024, 21:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как добавить QCheckBox в QTableView - готовое решение (Qt 5.8)  (Прочитано 8481 раз)
Rododendron
Гость
« : Июль 04, 2017, 11:30 »

Всю жизнь пользовался только QTableWidget и горя не знал, но тут попалась мне программа с QTableView, завязанной на модель QSqlTableModel.
Оказалось, добавить человеческие чекбоксы через делегаты, не так то просто. Предлагаю свое решение проблемы, т.к. нигде ничего не нашел толкового.

1. Добавление чекбоксов в третью колонку таблицы ui->table в конструкторе

Код:
for( int i=0; i<model.rowCount(); i++ )
    {
        QWidget *widget = new QWidget();
        QCheckBox *chBox = new QCheckBox();
        QHBoxLayout *layout = new QHBoxLayout;
        layout->setMargin(0);
        layout->setSpacing(0);
        layout->addWidget(chBox);
        layout->setAlignment( Qt::AlignCenter );
        widget->setLayout( layout );
        ui->table->setIndexWidget( model.index(i, 3), widget );

        if( model.data( model.index(i, 3) ).toBool() )
            chBox->setChecked( true );
        else
            chBox->setChecked( false );

        connect( chBox, SIGNAL(clicked(bool)), this, SLOT(onCheckBoxChecked(bool)) );
    }

Здесь мы создаем виджет и лайаут для выравнивания чекбокса по центру, добавляем родительский виджет в таблицу и связываем сигнал чекбокса со слотом. model - QSqlModelTable

2. Код обработчика сигнала чекбокса:

Код:
void ClassName::onCheckBoxChecked(bool isChecked)
{
    QCheckBox *widget = qobject_cast<QCheckBox*>(sender());

    for( int i=0; i<model.rowCount(); i++ )
    {
        if( ui->table->indexWidget(model.index(i, 3)) != NULL )
        {
            QWidget *cellWidget = qobject_cast<QWidget*>(ui->table->indexWidget(model.index(i, 3)))->layout()->itemAt(0)->widget();

            if( widget == qobject_cast<QCheckBox*>(cellWidget) )
            {
                if( isChecked )
                    model.setData( model.index(i, 3), true );
                else
                    model.setData( model.index(i, 3), false );

                model.submitAll();
            }
        }
    }
}

Здесь ничего хитрого, используем QObject::sender() для получения ссылки на объект, который испустил сигнал.

3. Теперь нужен код для добавления и удаления строк из таблицы.
Приведу кусок кода для удаления строки.

Сначла удаляем все чекбоксы после удаления выделенной строки:
Код:
if( !model.removeRows( selectedRow,1 ) )
{
// ERROR
}
else
{
    for( int i=0; i<model.rowCount(); i++ )
        ui->table->indexWidget( model.index(i,3) )->deleteLater();
}

Далее нам надо занести в базу изменения в модели и обновить ее, чтобы изменения отобразились на QTableView:
Код:
model.submitAll();
model.select();

Дальше остается заново добавить все чекбоксы, как в конструкторе.
Добавление строк в таблицу осуществляется по тому же принципу. При добавлении и удалении строк в таблице приходится каждый раз удалять все чекбоксы и добавлять заново, потому что при вызове QSqlTableModel::select() обновляется вся таблица. Не думаю, что стоит переживать по этому поводу, работа с базой все равно стоит дороже наших чекбоксов.

В принципе все. Остается убрать надписи true/false из ячеек с чекбоксами.
Я не стал долго ломать голову, и вам не советую.

Можно написать вот такой простенький делегат, который будет менять цвет текста и фона ячеек колонки на базовый:
Код:
class CheckBoxDelegate : public QItemDelegate
{
    Q_OBJECT

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
        QStyleOptionViewItem op(option);

        QPalette palette;
        op.palette.setColor(QPalette::Text, palette.color(QPalette::Base));
        op.palette.setColor(QPalette::Window, palette.color(QPalette::Base));
        op.palette.setColor(QPalette::Highlight, palette.color(QPalette::Base));
        op.palette.setColor(QPalette::HighlightedText, palette.color(QPalette::Base));

        QItemDelegate::paint(painter, op, index);
    }
};

Не забываем добавить делегат в конструкторе:
Код:
ui->table->setItemDelegateForColumn( 3, new CheckBoxDelegate );

Готово. Имеем чекбоксы по центру ячейки, которые нажимаются одним кликом и всегда видны, при этом никакого текста в ячейке нет.
« Последнее редактирование: Июль 04, 2017, 11:33 от Rododendron » Записан
Rododendron
Гость
« Ответ #1 : Июль 04, 2017, 12:26 »

Забыл добавить. Удаление всех чекбоксов при изменении количества строк в таблице не обязательно.
Удаление всего содержимого таблицы происходит при:
Код:
model.select();
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #2 : Июль 04, 2017, 13:43 »

А это не через Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const случаем делается?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #3 : Июль 04, 2017, 14:48 »

А это не через Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const случаем делается?

Нет, те прижимаются к краю ячейки
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.048 секунд. Запросов: 22.