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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QTableView и QCheckBox  (Прочитано 25088 раз)
LeX
Гость
« : Август 26, 2009, 19:53 »

Доброго времени суток.
Помогите решить проблему Грустный
Есть QTableView в котором необходимо поместить QCheckBox. Поместил я его по стандарту с помощью делегатов. Так вот проблема в том, что при редактировании ячейки таблицы всё хорошо (появляется QCheckBox), но когда курсор мыши попадает на QCheckBox, то текст в ячейке исчезает, а при отводе с него появляется опять.
В методе паинт уже перерисовал всё что только можно, но текст так и исчезает Грустный
Вопрос собственно в том, как сделать так чтобы при попадании на QCheckBox текст не исчезал, а оставался на месте.
Попутно, если кто-то занимался: как постоянно отображать QCheckBox?.
Вот собственно код делегата:

Код:
MyChBDelegate::MyChBDelegate(QObject *parent)
: QItemDelegate(parent)
{
}

QWidget *MyChBDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem& /* option */,const QModelIndex&  index ) const
{
QCheckBox *editor = new QCheckBox(parent);
int value = index.model()->data(index,Qt::EditRole).toInt();
editor->setCheckState(value != 0 ? Qt::Checked : Qt::Unchecked);
editor->installEventFilter(const_cast<MyChBDelegate*>(this));
return editor;
}

void MyChBDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QCheckBox *dsb = static_cast<QCheckBox*>(editor);
dsb->setCheckState(value != 0 ? Qt::Checked : Qt::Unchecked);
}

void MyChBDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex& index) const
{
QCheckBox *dsb = static_cast<QCheckBox*>(editor);
bool value = dsb->checkState();
model->setData(index, value);
}

void MyChBDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex& /* index */) const
{
editor->setGeometry(option.rect);
}

void MyChBDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QVariant value = index.model()->data(index,Qt::EditRole);
QString text = value.toInt() != 0 ? QString::fromUtf8("Да") : QString::fromUtf8("Нет");
QPalette palet;
palet.setColor(QPalette::Text,Qt::red);
palet.setColor(QPalette::HighlightedText,Qt::green);
palet.setColor(QPalette::Highlight,Qt::yellow);
QStyleOptionViewItem myOption = option;
myOption.palette=palet;
myOption.displayAlignment = Qt::AlignCenter;

drawDisplay(painter,myOption,myOption.rect,text);
drawFocus(painter,myOption,myOption.rect);
}
Записан
Rcus
Гость
« Ответ #1 : Август 26, 2009, 20:01 »

"broken as intended" ©
::paint управляет отображением вне режима редактирования, а QCheckBox в режиме редактирования.
/** решил бы это через Qt::CheckStateRole без привлечения своих делегатов */
Записан
LeX
Гость
« Ответ #2 : Август 26, 2009, 20:28 »

"broken as intended" ©
::paint управляет отображением вне режима редактирования, а QCheckBox в режиме редактирования.
/** решил бы это через Qt::CheckStateRole без привлечения своих делегатов */

Ды рад бы, только используется QSqlTableModel и нельзя переопределить мне метод data  и flags Грустный
Если подскажешь как по другому можно, я буду рад Улыбающийся
Записан
Rcus
Гость
« Ответ #3 : Август 27, 2009, 03:36 »

Эм то есть как это нельзя? Я пропустил введение final классов в C++? А вещь еще есть проксии модели.
Записан
LeX
Гость
« Ответ #4 : Август 27, 2009, 08:30 »

Эм то есть как это нельзя? Я пропустил введение final классов в C++? А вещь еще есть проксии модели.

Да всё там можно  Веселый Просто говорю что мне нельзя это сделать (поставлена задача таким образом (Использовать в качестве модели QSqlTableModel (нельзя мне говорят переопределять методы flags и data дабы не потерять QSqlTableModel::onManualSubmit запар говорят меньше будет с сохранением результатов, а там в другом месте запар выше крыши появляется) (я и так уже извратился переопределив метод setQuery чтобы писать запросы полнофункциональные (хз чем обернётся, но я бы лучше не делал этого)))Грустный) Вот и парюсь (извращаюсь) вешая QCheckBox в делегата  Грустный

Так есть способ исправить этот недостаток в делегате?
« Последнее редактирование: Август 27, 2009, 08:44 от LeX » Записан
sergeyvl12
Гость
« Ответ #5 : Август 27, 2009, 10:23 »

Цитировать
Попутно, если кто-то занимался: как постоянно отображать QCheckBox?.

Не знаю поможет это или нет, но я недавно не мог избавиться от чекбоксов (без всяких делегатов).

Избавился...

Вот ссылка: http://www.prog.org.ru/topic_10393_0.html

Они выводились как раз слева от текста. Их можно сделать редактируемыми Улыбающийся
« Последнее редактирование: Август 27, 2009, 10:24 от sergeyvl12 » Записан
LeX
Гость
« Ответ #6 : Август 27, 2009, 10:41 »

Не знаю поможет это или нет, но я недавно не мог избавиться от чекбоксов (без всяких делегатов).

Избавился...

Вот ссылка: http://www.prog.org.ru/topic_10393_0.html

Они выводились как раз слева от текста. Их можно сделать редактируемыми Улыбающийся


Я же говорю нельзя для моей задачи переопределять методы flags и data.
Я мог бы сделать так:
Код:
Qt::ItemFlags MyModel::flags(const QModelIndex &index) const 
{
        Qt::ItemFlags flags = QSqlTableModel::flags(index);
        if (index.column() > 1 && index.column() < 3)
                flags |= Qt::ItemIsEditable;
        if (index.column() == 3)
                flags |= Qt::ItemIsUserCheckable;
        return flags;
}

QVariant MyModel::data(const QModelIndex &index,int role) const
{
        QVariant value = QSqlTableModel::data(index, role);
        switch (role)
        {
        . . .
           case Qt::CheckStateRole:
             if (index.column() == 3)
                return (QSqlTableModel::data(index).toInt() != 0) ? Qt::Checked : Qt::Unchecked;
                        else
                          return value;
        . . .
        }
        return value;
}

Мне нужно решение проблемы через делегаты, если это возможно Непонимающий
Записан
spectre71
Гость
« Ответ #7 : Август 28, 2009, 09:19 »

Мне нужно решение проблемы через делегаты, если это возможно Непонимающий
Легко.
1) Определяешь в своей модели получение QPixmap от индекса.
2) В делегате получаешь QPixmap для индекса и отрисовываешь

Отрисовка QCheckBox примерно такая:

Код
C++ (Qt)
 drawCheckBox(QStyle::State_Off);
 drawCheckBox(QStyle::State_On);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_Off);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_On);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_Off | QStyle::State_MouseOver);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_On  | QStyle::State_MouseOver);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_Off | QStyle::State_MouseOver | QStyle::State_Sunken);
 drawCheckBox(QStyle::State_Enabled | QStyle::State_On  | QStyle::State_MouseOver | QStyle::State_Sunken);
 
 
QPixmap drawCheckBox(QStyle::State State, QWidget* w) {
 QStyle* Style = QApplication::style();
 QStyleOptionButton StyleOptionButton;
 if(w) {StyleOptionButton.initFrom(w);}
 StyleOptionButton.state = State;
 QRect r = Style->subElementRect (QStyle::SE_CheckBoxIndicator, &StyleOptionButton);
 StyleOptionButton.rect = r;
 if(!(State&QStyle::State_Enabled)) {
   QPalette p = QApplication::palette();
   p.setColor(QPalette::Active, QPalette::Text, p.color(QPalette::Disabled, QPalette::Text));
   StyleOptionButton.palette = p;
 }
 
 QPixmap pixmap(r.width(), r.height());
 pixmap.fill(Qt::transparent);
 QPainter painter;
 painter.begin(&pixmap);
 painter.translate(-r.left(), -r.top());
 Style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &StyleOptionButton, &painter);
 painter.end();
 return pixmap;
}
Записан
LeX
Гость
« Ответ #8 : Август 28, 2009, 13:25 »

Легко.
1) Определяешь в своей модели получение QPixmap от индекса.
2) В делегате получаешь QPixmap для индекса и отрисовываешь
А поподробнее рассказать можешь? Я просто этим не занимался ни разу да иопыта в Qt не особо много.

Кстати через флаги сделал. Всё гуд получилось Улыбающийся
Вот код может кому пригодится
Код:
Qt::ItemFlags QPGTableModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QSqlTableModel::flags(index);
if (index.column() == 4)
flags |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
return flags;
}

QVariant QPGTableModel::data(const QModelIndex &index,int role) const
{
QVariant value = QSqlTableModel::data(index, role);
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
if(index.column()==4)
return value.toInt() != 0 ? QString::fromUtf8("Да") : QString::fromUtf8("Нет");
return QSqlTableModel::data(index,role);
case Qt::CheckStateRole:
if (index.column() == 4)
return (QSqlTableModel::data(index).toInt() != 0) ? Qt::Checked : Qt::Unchecked;
}
return value;
}

bool QPGTableModel::setData(const QModelIndex &index,const QVariant &value,int role)
{
if(role==Qt::CheckStateRole)
return QSqlTableModel::setData(index,value.toBool(),Qt::EditRole);
return QSqlTableModel::setData(index,value);
}

P. S. Руководитель сказал сделать через делегатов  Грустный
« Последнее редактирование: Август 28, 2009, 14:40 от LeX » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #9 : Октябрь 18, 2009, 01:44 »

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

Код
C++ (Qt)
#ifndef __CHECKBOX_DELEGATE_H__
#define __CHECKBOX_DELEGATE_H__
 
#include <QItemDelegate>
 
class CChecBox_Delegate : public QItemDelegate
{
Q_OBJECT;
QString m_sIconPath;
QString m_sText;
 
public:
CChecBox_Delegate( QObject * parent = 0 );
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;
void paint( QPainter * painter, const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
 
inline void setIconPath( QString sVal ) { m_sIconPath = sVal; }
inline void setText( QString sVal )     { m_sText = sVal; }
};
 
#endif // __CHECKBOX_DELEGATE_H__
 
 


Код
C++ (Qt)
 
#include "CheckBox_Delegate.h"
 
#include <QCheckBox>
#include <QStylePainter>
#include <QPalette>
#include <QAbstractItemView>
#include <QDebug>
 
CChecBox_Delegate::CChecBox_Delegate( QObject *parent ) : QItemDelegate(parent)
{
m_sIconPath = "";
m_sText = "";
}
 
QWidget * CChecBox_Delegate::createEditor( QWidget * parent,
 const QStyleOptionViewItem& /* option */,
 const QModelIndex&  index ) const
{
QCheckBox * pEditor = new QCheckBox( parent );
pEditor->setText( m_sText );
pEditor->setCheckable( true );
pEditor->setIcon( QIcon( m_sIconPath ) );
 
pEditor -> installEventFilter( const_cast<CChecBox_Delegate*>( this ) );
return pEditor;
}
 
void CChecBox_Delegate::setEditorData( QWidget * editor, const QModelIndex &index) const
{
int value = index.model()->data( index, Qt::EditRole ).toInt();
QCheckBox * cb = static_cast<QCheckBox*>( editor );
 
cb->setChecked( value );
}
 
void CChecBox_Delegate::setModelData( QWidget * editor,
  QAbstractItemModel *model,
  const QModelIndex& index) const
{
QCheckBox * cb = static_cast<QCheckBox*>( editor );
model->setData( index, cb->isChecked() );
}
 
void CChecBox_Delegate::updateEditorGeometry( QWidget *editor,
  const QStyleOptionViewItem &option,
  const QModelIndex& index ) const
{
editor->setGeometry( option.rect );
}
 
void CChecBox_Delegate::paint( QPainter * painter, const QStyleOptionViewItem &option,
 const QModelIndex &index ) const
{
QWidget * w = dynamic_cast<QWidget *>( painter->device() );
if ( w )
{
QStylePainter p( w );
QStyleOptionButton opt;
opt.text = m_sText;
opt.icon = QIcon( m_sIconPath );
opt.iconSize = QSize( 24, 24 );
opt.initFrom( w );
opt.rect = option.rect;
 
bool bChecked = index.data().toInt() > 0;
if ( bChecked )
opt.state |= QStyle::State_On;
p.drawControl( QStyle::CE_CheckBox, opt );
}
 
drawFocus( painter, option, option.rect );
}
 
 
Записан
cdsmika
Гость
« Ответ #10 : Октябрь 25, 2009, 20:56 »

Подскажите как расположить QCheckBox по центру колонки при редактировании ячейки в QTableView?
Записан
cdsmika
Гость
« Ответ #11 : Октябрь 25, 2009, 21:00 »

Кто-нибудь использовал такой подход:
Код
C++ (Qt)
QItemEditorFactory *factory = new QItemEditorFactory;
factory->registerEditor(QVariant::Bool, new QStandardItemEditorCreator<QCheckBox>());
QItemEditorFactory::setDefaultFactory(factory);
?
Записан
cdsmika
Гость
« Ответ #12 : Октябрь 25, 2009, 21:32 »

Кто-нибудь использовал такой подход:
Код
C++ (Qt)
QItemEditorFactory *factory = new QItemEditorFactory;
factory->registerEditor(QVariant::Bool, new QStandardItemEditorCreator<QCheckBox>());
QItemEditorFactory::setDefaultFactory(factory);
?
Так все проще.
Вот прорисовка:
void paint( QPainter * painter, const QStyleOptionViewItem &option,
                    const QModelIndex &index ) const
{
   const QSqlRelationalTableModel *sqlModel =
         qobject_cast<const QSqlRelationalTableModel *>(
               qobject_cast<const QSortFilterProxyModel *>( index.model() )->sourceModel() );

   if ( sqlModel->record(index.row()).field(index.column()).typeID() == 16 )
   {
      QItemDelegate::drawBackground( painter, option, index );
      QItemDelegate::drawCheck( painter, option, option.rect, index.data(Qt::EditRole).toBool() ? Qt::Checked : Qt::Unchecked );
      QItemDelegate::drawFocus( painter, option, option.rect );

   }
   else
      QItemDelegate::paint(painter, option, index);
}
Записан
Barmaglodd
Гость
« Ответ #13 : Ноябрь 03, 2009, 14:51 »

У решений с createEditor есть один большой минус - если ячейка не в фокусе, надо 2 раза жать на мышку, чтобы изменить состояние чекбокса.
В архиве делегат, который работает, как при установке Qt::ItemIsUserCheckable.
Записан
Yuriy
Гость
« Ответ #14 : Август 20, 2011, 22:53 »

Barmaglodd, спасибо огромное. Давно с этим зверьком боролся. Ваш код великолепно сработал.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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