Russian Qt Forum
Июня 13, 2025, 11:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Позиционирование QTableView  (Прочитано 7334 раз)
radislav72
Гость
« : Ноября 20, 2010, 19:32 »

Здравствуйте!

Есть такая ситуация: TableView связан с некоторой моделью, которая представляет набор данных из БД. После того как юзер выбрал запись в таблице (с известным первичным ключем в БД) и отредактировал ее, нужно обновить данные на экране. Для этого перечитывается модель, и после этого нужно позиционировать ее на отредактированной записи по заранее известному первичному ключу.

С такой целью я начал использовать код типа :
Код:
for (int i = 0; i < model->rowCount(); ++i)
{
  if (model->record(i).value("id").toString() == d->id)
  {
    ui->tabv->selectRow(i);
    break;
  }
}

Но что-то подсказывает, что существует более оптимальный способ Улыбающийся. По крайней мере, наличие метода setSelectionModel вроде как указывает на это. Но почему-то не получается использовать его. Приведите, пожалуйста, кому не совсем лень, простенький способ использования setSelectionModel (если он вообще решает поставленное задание)...

Буду преочень благодарен.
Записан
crossly
Гость
« Ответ #1 : Ноября 20, 2010, 19:49 »

можно запоминать индекс а после редактирования делать
Код:
void QAbstractItemView::scrollTo ( const QModelIndex & index, ScrollHint hint = EnsureVisible )   [pure virtual]

а так ли необходимо сразу обновлять данные в БД... или можно подождать... ??
Записан
radislav72
Гость
« Ответ #2 : Ноября 20, 2010, 20:34 »

Цитировать
а так ли необходимо сразу обновлять данные в БД...
Может, я неправильно выразился... Имеется ввиду, что юзер выбрал в таблице запись, щелкнул некую кнопку, появилась форма, в которой он изменил что-то, нажал "Сохранить" и сохранил данные в БД (если сохранил, значит ему нужно). После этого нужно обновить их на экране (перечитать модель из БД)- это нужно по спецификации. Для этого- перейти к редактируемой записи.

А можно небольшой пример насчет scrollTo : как по извесному id записи можно перейти к ней... Или лучше использовать какой-то другой способ?
Записан
crashsp
Гость
« Ответ #3 : Ноября 20, 2010, 21:52 »

Когда ты нажимаешь на ячейку которую хочешь отредактировать появляется твоя форма соответственно тебе известен QModelIndex этой ячейки crossly тебе уже написал что достаточно запомнить его и как только произошла  выборка(которая после редактирования) воспользоваться функцией я не пользовался функцией 
void QAbstractItemView::scrollTo ( const QModelIndex & index, ScrollHint hint = EnsureVisible )

всегда делал так
допустим есть переменная  QModelIndex editIndex;
следил в какой ячейки начинается редактирование("Нажатие некой кнопки)"),ну допустим ячейка у которой модельный индекс равен второй колонки и третьей строки,делал переменную editIndex = индексу ячейки которую редактируем Все. Как только ты отредактировал, сделал повторную выборку вызвал : ui->tabv->selectRow(editIndex.row());
исходя из примера будет выделена третья строка
Так что собственно тебе не надо пускать циклы и запоминать ID достаточно знать строку которую редактируешь
 
« Последнее редактирование: Ноября 20, 2010, 22:02 от crashsp » Записан
radislav72
Гость
« Ответ #4 : Ноября 20, 2010, 22:24 »

Спасибо за понятный ответ Улыбающийся

Еще вопрос: если запомнить QModelIndex editIndex (до редактирования записи), и если после перечитывания данных из БД для модели окажется что искомая строка "не на своем месте" (например, по причине того, что другой юзер по сети добавил/ удалил записи), то насколько я понимаю этот метод не подойдет?
Записан
BRE
Гость
« Ответ #5 : Ноября 20, 2010, 22:28 »

Тут есть тонкий момент.
Предположим таблица сортируется по имени. Мы начинаем редактировать запись с именем "Яша", эта запись располагается внизу таблицы. Мы меняем имя на "Афанасий". После перечитывания таблицы эта запись становиться первой в таблице. Курсор должен переместиться на нее, а при таком подходе он останется внизу на совершенно другой записи.
IMHO, неплохо привязываться к id записи, но в дальнейшем поиск номера строки для записи с нужным id может оказаться довольно тяжелой операцией, особенно на очень больших таблицах.
Записан
radislav72
Гость
« Ответ #6 : Ноября 20, 2010, 22:34 »

Тут есть тонкий момент...
Да, это еще один пример нужности id.
А как лучше выполнить позиционирование в таком случае? Тот цикл, с которого я начинал?
Записан
BRE
Гость
« Ответ #7 : Ноября 20, 2010, 23:02 »

А как лучше выполнить позиционирование в таком случае? Тот цикл, с которого я начинал?
Ох, "знал бы прикуп...."  Улыбающийся
Прямой перебор на больших объемах это всегда не эффективно.
С одной стороны предоставление пользователю таблицы на много тысяч записей не нужно, пользователь все равно не сможет с этой таблицей эффективно работать. Т.е. можно продумать удобную структуру выборки нужных записей из большой таблицы (древовидная структура разделов/фильтры/быстрый поиск/?), так что бы пользователь в любой момент времени видел не большую нужную часть данных. Можно быстро найти номер записи по id.
С другой стороны пользователь может не придерживаться такой структуры и все писать в корень. Получи тормоза при поиске.
Хорошо бы, что бы сервер БД мог сообщать порядковый номер записи в таблице по ее id.
Сейчас я стараюсь ограничивать объем данных выдаваемый пользователю, использую свои модели на базе обычных запросов (QSqlQuery) и ищу порядковый номер записи перебором.
Записан
radislav72
Гость
« Ответ #8 : Ноября 21, 2010, 07:32 »

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

Спасибо!
Записан
crashsp
Гость
« Ответ #9 : Ноября 21, 2010, 08:02 »

Цитировать
(например, по причине того, что другой юзер по сети добавил/ удалил записи), то насколько я понимаю этот метод не подойдет?
Не подойдет((
Цитировать
Предположим таблица сортируется по имени. Мы начинаем редактировать запись с именем "Яша", эта запись располагается внизу таблицы. Мы меняем имя на "Афанасий"
предпологалоь что редактирование не происходит по сортируемой колонки, отталкивался то своих заморок(

кстати посмотри вот эту функцию
QModelIndexList QAbstractItemModel::match ( const QModelIndex & start, int role, const QVariant & value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap ) ) const [virtual]
может поможет я думаю она все же быстрее чем перебор
Записан
radislav72
Гость
« Ответ #10 : Ноября 21, 2010, 10:15 »

кстати посмотри вот эту функцию QModelIndexList QAbstractItemModel::match ( const QModelIndex & start, int role, const QVariant & value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags( Qt::MatchStartsWith | Qt::MatchWrap ) ) const [virtual]

Спасибо, вариант интересный. Надо будет попробовать на больших таблицах, что быстрее... Что-по подсказывает, что match таки должен шустрее искать чем цикл Улыбающийся

Конечный вариант:
Код:
    QModelIndex six = modFileDeposites->index(0, nmsFileDeposites::fldId);
    QModelIndexList ixl = modFileDeposites->match(six, Qt::DisplayRole, id, 1, Qt::MatchExactly);
    if (!ixl.empty()) ui->tabv->selectRow(ixl.value(0).row());
« Последнее редактирование: Ноября 21, 2010, 10:28 от radislav72 » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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