четверг, 29 апреля 2010 г.

Нюансы разработки GUI базы данных на PyQt

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

Мне попортили определенное количество крови следующие вещи:


  • Неотъемлемой частью инициализации QDataWidgetMapper является его позиционирование на редактируемой строке модели (setCurrentIndex). Нужно иметь в виду, что маппер не проверяет корректность индекса, за этим должен следить разработчик. Особенно плохо когда маппер некорректно позиционируется для заполнения вновь созданной строки. В этом случае по внешнему виду формы никак не определишь что маппер проинициализирован некорректно.

    Резюме: Внимательно следите, что передается в функцию QDataWidgetMapper.setCurrentIndex

  • Позиционировать маппер следует после установки всех связок колонок моделей с соответствующими виджетами. Только в этом случае виджеты корректно заполнятся данными из модели. Особенно неприятно, когда эту ошибку допускаешь одновременно с вышеописанной, хрен поймешь, откуда ноги растут.

    Резюме: Убедитесь, что вызов функции QDataWidgetMapper.setCurrentIndex (или другой функции позиционирования) всегда следует после всех вызовов QDataWidgetMapper.addMapping

  • Похожая особенность существует у модели QSqlRelationalTableModel. Чтобы корректно заполнились внутренние данные для связанных моделей, все отношения необходимо устанавливать (setRelation) до заполнения модели данными (select).

    Резюме: Убедитесь, что вызов функции QSqlRelationalTableModel.select всегда следует после всех вызовов QSqlRelationalTableModel.setRelation

  • С помощью QDataWidgetMapper особенно удобно реализовывать редактирование модели QSqlRelationalTableModel. Он автоматически заполняет список выбора у соответствующих комбо-боксов и так же автоматически положит в модель нужное значение внешнего ключа. Красота. Но если забыть при инициализации маппера указать ему использовать QSqlRelationalDelegate, вся красота молча отваливается. Никаких сообщений не будет, просто функционал не будет работать.

    Резюме: Если вы используете QDataWidgetMapper для редактирования модели QSqlRelationalTableModel, убедитесь, что при инициализации маппера была вызвана функция QDataWidgetMapper.setItemDelegate(QSqlRelationalDelegate())

  • Типовая задача обработки изменения позиции в QTableView решается несколько неочевидно (по крайней мере для меня ;). У вьюхи необходимо запросить модель выделения (QTableView.selectionModel()) и прицепить обработчик к сигналу currentRowChanged модели выделения. В дизайнере формы этого сделать, к сожалению нельзя.

1 комментарий: