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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QTableView и QTableModel  (Прочитано 14625 раз)
Jager-ntr
Гость
« : Апрель 21, 2008, 16:07 »

Добрый вечер. Встал вопрос - как можно реализовать следующее: есть таблица, в каждой ячейки имеются данные(какая-то надпись, например),но этой же ячейке соответствует набор данных(который визуально не отображается), который отображается в виде нового окна с таблицей в нем, по двойному нажатию на выбранную ячейку?
Записан
ритт
Гость
« Ответ #1 : Апрель 21, 2008, 16:23 »

установить нужные данные в нужные индексы для нужн(ой роли|ых ролей)
читать документация по модель-вью
Записан
Jager-ntr
Гость
« Ответ #2 : Апрель 22, 2008, 09:41 »

да,с этим все нормально решилось. Мне надо, чтобы по двойному щелчку на ячейке происходили определенные действия.Для этого я делаю следующее:
Код:
pTable = new QTableView();
......//создание модели
pTable->setModel(model);
Object::connect(pTable, SIGNAL(doubleClicked(QModelIndex& index)),this, SLOT(slotItemClicked(QModelIndex& index)));
но ничего не происходит.
Записан
denka
Гость
« Ответ #3 : Апрель 22, 2008, 10:32 »

1 В Qt нет класса Object, но думаю это опечатка Улыбающийся
2 В макросах типа SIGNAL или SLOT вы должны указывать прототип ф-ции без формальных параметров. Т.е.
QObject::connect(pTable, SIGNAL(doubleClicked(QModelIndex& )),this, SLOT(slotItemClicked(QModelIndex& )));
Записан
Jager-ntr
Гость
« Ответ #4 : Апрель 22, 2008, 12:00 »

Да, с Object у меня опечатка вышла,а с сигнал-слотом неправильно указал сигнатуру. У меня в каждой ячейке таблицы содержится объект класса CTableItem(мной написанный). QTableView строится нормально,а для получения айтема ячейки использую следющий код:
Код:
CTableItem* item = static_cast<CTableItem*>(pTable->model()->index(index.row(), index.column()).internalPointer();//переменная index передается из сигнала по двойному нажатию на ячейку QTableView
но если затем попытаться получить данные из этого айтема,то вылетает с ошибкой
Записан
denka
Гость
« Ответ #5 : Апрель 22, 2008, 12:33 »

Проверьте не возвращаете ли вы нулевой указатель internalPointer(). Да и вобще лучше бы сразу привели код, как вы формируете индекс в модели. Лично мне не понятно из такого кода в чем может быть проблема Улыбающийся
Записан
Jager-ntr
Гость
« Ответ #6 : Апрель 22, 2008, 13:08 »

с концепцией модель-представление раньше не работал,отсюда и проблемы. Формирование индекса в своей модели я не переопределял,а предыдущий код возвращает как раз нулевой указатель...Пример создания индекса есть?смотрел пример для дерева,но тот вариант не подходит
Записан
denka
Гость
« Ответ #7 : Апрель 22, 2008, 14:06 »

Смотрим реализацию ф-ции index в QAbstractTableModel:

QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent) const
{
    return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
}

Все что вам нужно сделать, так это заменить 3 параметр ф-ции createIndex на соответствующие данные. Анализируете строку и колнку, находите для них соответствующий CTableItem(к сожелению не знаю как у вас организовано хранение этих итемов) и передаете указатель на этот итем в ф-цию createIndex.
Записан
Jager-ntr
Гость
« Ответ #8 : Апрель 22, 2008, 15:22 »

для простоты,объекты этого класс должны находиться в каждой ячейке:
Код:
class CTableItem
{
public:
    CTableItem(QVariant capation = "test",const QList<QVariant> &data = QList<QVariant>());
    ~CTableItem();

    QList<QVariant> itemData; //список данных,относящихся к ячейке
    QVariant itemCaption; //то, что будет отображаться в ячейке таблицы
private:
};
я не закрывал никакие члены,не писал никаких функций для доступа к ним.Для пробы напрямую к ним обращаюсь.
Далее код переопределенных методов в классе моей модели:
Код:
Для хранения айтемов CTableItem в классе модели используется QHash<QModelIndex, CTableItem> m_hash

CDragDropModel::CDragDropModel(int nRows, int nColumns, QObject* pobj) : QAbstractTableModel(pobj),
m_nRows(nRows),                   //количество строк в модели
m_nColumns(nColumns)            //количество столбцов в модели
{
}

CDragDropModel::~CDragDropModel()
{
}
QVariant CDragDropModel::data(const QModelIndex &index, int nRole) const    //возвращаю текст, отображаемый в ячейке
{
if(!index.isValid())
return QVariant("Error");
CTableItem item = m_hash[index];
return (nRole == Qt::DisplayRole || nRole == Qt::EditRole) ? item.itemCaption : QVariant();
}
bool CDragDropModel::setData(QModelIndex &index, const CTableItem& value, int nRole)  //устанавливаю данные в модель по индексу
{
if(index.isValid() && nRole == Qt::DisplayRole)
{
m_hash[index] = value;
emit dataChanged(index, index);
return true;
}
return false;
}
int CDragDropModel::rowCount(const QModelIndex &) const
{
return m_nRows;
}
int CDragDropModel::columnCount(const QModelIndex &) const
{
return m_nColumns;
}
Qt::ItemFlags CDragDropModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractItemModel::flags(index);
return (index.isValid()) ? (flags | Qt::ItemIsEditable) : flags;
}
QModelIndex CDragDropModel::index(int row, int column, const QModelIndex &index) const    //формирование индекса !!! тут не знаю, правильно ли
{
if(!hasIndex(row, column, index))
return QModelIndex();
CTableItem item = m_hash[index];
return createIndex(row, column, &item);
}

Так я заношу данные в модель:
Код:
	CDragDropModel* model = new CDragDropModel(3, 3);
for(int nRow = 0; nRow < 3; nRow++)
for(int nCol = 0; nCol < 3; nCol++)
{
QModelIndex index = model->index(nRow, nCol, QModelIndex());
QList<QVariant> itemData;
itemData.append(QVariant("OK"));
itemData.append(QVariant("Err"));
CTableItem item(QVariant("Data"), itemData);
model->setData(index, item, Qt::DisplayRole);
}
pTable = new QTableView();
pTable->setModel(model); //тут возникает ошибка
В итоге, ошибка вылетает, когда пытаюсь установить для pTable модель
Записан
denka
Гость
« Ответ #9 : Апрель 22, 2008, 16:58 »

Думаю все таки вам стоит почитать соответствующий раздел ассистента. Ф-ция index в модели используеться именно для формирования индекса модели. Третим параметром туда передаеться индекс парента, вы же используете его для доступа к даным в хеше, интерпритируя его как текущий индекс. Это не есть правельно!!!. Предлагаю следующее:
1) Изменить форму хранения CTableItem. Так чтоб доступ не зависел от QModelIndex. Скажем пускай будет так
typedef QPair<int, int> TableIndex;
QHash<TableIndex, CTableItem*> m_hash;
здесь еще надо реализовать ф-цию qHash() (см. Assistant). Вторым параметром предпочтительней использовать указатель. Тот вариант который был у вас не коректен. Если вы еще раз посмотрите на код в ф-ции index то увидете что там вы возвращаете адрес локального объекта. Это не позволительно, т.к. при фыходе из этой ф-ции локальный объект разрушаеться и у вас остаеться указатель на "муссор". Из-за этого могут быть проблемы хуже чем с нудевым указателем Улыбающийся
2) Ф-ция data приймет такой вид:
QVariant CDragDropModel::data(const QModelIndex &index, int nRole) const
{
   if(index.isValid())
           {
              if ( nRole == Qt::DisplayRole || nRole == Qt::EditRole ) // вобще EditRole на сколько я знаю используеться для установки данных
              {
                  if ( CTableItem * item = static_cast<CTableItem *>(index.internalPointer()) ) // коректный индекс уже содержит указатель на нужные нам данные
                  {
                      return item->itemCaption;
                  }
              }       
           }
   return QVariant();
}
3) ф-ция index будет выглядеть так:
QModelIndex CDragDropModel::index(int row, int column, const QModelIndex &parent) const   
{
   if(!hasIndex(row, column, parent))
      return QModelIndex();
     TableIndex index = qMakePair( row, column );
   CTableItem * item = m_hash[index];
   return createIndex(row, column, item); // вот теперь ф-ция  internalPointer() будет возвращать указатель на нужные нам данные
}
4) ф-ция setData может быть такой
bool CDragDropModel::setData(QModelIndex &index, const CTableItem& value, int nRole)  {
   if(index.isValid() && nRole == Qt::EditRole)// установка происходит по EditRole!!! у вас было DisplayRole
   {
       if ( CTableItem * item = static_cast<CTableItem *>(index.internalPointer()) ) // коректный индекс уже содержит указатель на нужные нам данные
       {
          item->itemCaption = value;
          emit dataChanged(index, index);
          return true;
       }
   }
   return false;
}
5) Понятия не имею расширяеться у вас таблица или остаеться статичной взависемости от этого вам уже самому решать как формировать ваш хеш данных.
Записан
Вячеслав
Гость
« Ответ #10 : Апрель 22, 2008, 20:27 »

А вообще IMHO проще глянуть на examples\itemviews\simpletreemodel тама все прозрачно разжевано...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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