сигнал dataChanged не работает с ComboBoxDelegate

Моя проблема заключается в следующем:

Eсть QTableViewи QStandardItemModel используется таким образом:

ui->tableView->setModel(model);
model->setItem(myrow, mycolumn, myQStandardItem);

и comboboxdelegate:

ComboBoxDelegate* mydelegate = new ComboBoxDelegate();
ui->tableView->setItemDelegateForColumn(mycolumn,mydelegate);

Каждый раз, когда значение ячейки таблицы изменяется (с помощью поля со списком), мне нужно поймать новое значение и индекс только что измененной ячейки. Я использую сигнал dataChaged связан с моделью следующим образом:

connect(model,SIGNAL(dataChanged(QModelIndex&,QModelIndex&)),this,SLOT(GetChangedValue(QModelIndex&)));

но это не работает, он никогда не вызывает метод GetChangedValue хотя поле со списком изменило свое значение. Я пропускаю какой-либо шаг?

Здесь под кодом ComboBoxDelegate:

class ComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:

ComboBoxDelegate(QVector<QString>& ItemsToCopy,QObject *parent = 0);
~ComboBoxDelegate();
void setItemData(QVector<QString>& ItemsToCopy);

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;private:
QVector<QString> Items;

};

ComboBoxDelegate::ComboBoxDelegate(QVector<QString>&  ItemsToCopy,QObject  *parent)
:QStyledItemDelegate(parent)
{
setItemData(ItemsToCopy);
}ComboBoxDelegate::~ComboBoxDelegate()
{
}QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const     QStyleOptionViewItem &option, const QModelIndex &index) const
{

QComboBox* editor = new QComboBox(parent);
editor->setEditable(true);for (int i = 0; i < Items.size(); ++i)
{
editor->addItem(Items[i]);
}editor->setStyleSheet("combobox-popup: 0;");

return editor;
}void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex  &index) const
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
QString currentText = index.data(Qt::EditRole).toString();
int cbIndex = comboBox->findText(currentText);
comboBox->setCurrentIndex(cbIndex);
}void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel    *model, const QModelIndex &index) const
{
QComboBox *comboBox = static_cast<QComboBox*>(editor);
model->setData(index, comboBox->currentText(), Qt::EditRole);

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

}void ComboBoxDelegate::setItemData(QVector<QString>&  ItemsToCopy)
{
for (int row = 0; row < ItemsToCopy.size(); ++row)
{

Items.push_back(ItemsToCopy[row]);}

}

1

Решение

Проблема с вашей реализацией делегата заключается в том, что вы не излучаете commitData сигнал при изменении комбинированного индекса. Это указано в документации Qt:

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

Вы можете иметь поле со списком в качестве члена класса делегата и подключить currentIndexChanged сигнал комбинированного окна в какой-либо слот, который излучает commitData :

#include <QItemDelegate>

#include <QComboBox>

class ComboBoxDelegate: public QItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(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;

QStringList comboItems;

mutable QComboBox *combo;

private slots:

void setData(int val);

};

ComboBoxDelegate::ComboBoxDelegate(QObject *parent ):QItemDelegate(parent)
{
comboItems<<"Item 1"<<"Item 2"<<"Item 3";
}

QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
combo = new QComboBox( parent );
QObject::connect(combo,SIGNAL(currentIndexChanged(int)),this,SLOT(setData(int)));
combo->addItems(comboItems);
combo->setMaxVisibleItems(comboItems.count());
return combo;
}

void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString text = index.model()->data( index, Qt::DisplayRole ).toString();

int comboIndex = comboItems.indexOf(QRegExp(text));

if(comboIndex>=0)
(static_cast<QComboBox*>( editor ))->setCurrentIndex(comboIndex);
}

void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
model->setData( index, static_cast<QComboBox*>( editor )->currentText() );
}void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry( option.rect );
}

void ComboBoxDelegate::setData(int val)
{
emit commitData(combo);
//emit closeEditor(combo);
}

Как вы видите currentIndexChanged сигнал комбо-бокса подключен к setData слот, который передает данные в модель. Также вы должны объявить combo-box как изменяемый для его обновления в createEditor который является постоянным. Если элемент данных объявлен изменяемым, то законно присвоить значение этому элементу данных из const функция-член.

Теперь dataChanged сигнал будет излучаться при изменении индекса комбинированного списка.

1

Другие решения


По вопросам рекламы [email protected]