Russian Qt Forum
Ноябрь 23, 2024, 08:24
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Базы данных
>
SqlTableModel/TableView тормоза
Страниц: [
1
]
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: SqlTableModel/TableView тормоза (Прочитано 6794 раз)
igorko
Гость
SqlTableModel/TableView тормоза
«
:
Август 04, 2006, 16:46 »
Я сделал SqlTableModel, TableView и Delegate.
Пока записей не много, то все работает нормально.
Когда назаписывал около 1500 записей - стало ужасно тормозить
(Сами запросы выполняются не более 2 сек в pgAdmine)
Посоветуйте, пожалуйста, как узнать где нужно оптимизировать.
Записан
Alexei
Гость
SqlTableModel/TableView тормоза
«
Ответ #1 :
Август 05, 2006, 07:42 »
Какой режим debug или release? Что в делегате? Подробнее, пожалуйста.
Записан
igorko
Гость
SqlTableModel/TableView тормоза
«
Ответ #2 :
Август 06, 2006, 14:48 »
Спасибо Alexei, за намерение помочь.
Режим - debug
Вот весь делегат:
/*
delegate.cpp
A delegate that allows the user to change values from the model
using a combo box widget.
*/
#include <QtGui>
#include <QtSql>
#include "delegate.h"
#include "mymodels.h"
MyDelegate::MyDelegate(QObject *parent)
: QItemDelegate(parent)
{
// installEventFilter(this);
}
QWidget *MyDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem & option,
const QModelIndex & index) const
{
MySqlTableModel *m = (MySqlTableModel*)(index.model());
if ( m->isForeignKey( index.column() ) )
{
QString query = QString ("SELECT %1 FROM %2") // ORDER BY %1")
.arg( m->getForeignFieldName( index.column() ) )
.arg( m->getForeignTableName( index.column() ) );
QSqlQuery q(query);
QStringList sl;
while (q.next())
sl += q.value(0).toString();
MyComboBox *comboEditor = new MyComboBox(sl, parent);
comboEditor->setObjectName("ComboEditor");
comboEditor->installEventFilter(const_cast<MyDelegate*>(this));
return comboEditor;
}
QDateEdit *dateEditor;
QTextEdit *textEditor;
QLineEdit *lineEditor;
switch ( m->getFieldType( index.column() ) )
{
case QVariant::Date:
dateEditor = new QDateEdit(parent);
dateEditor->setDisplayFormat("dd.MM.yyyy");
return dateEditor;
case QVariant::String:
if ( m->getFieldLength( index.column() ) == -1 ) // if length = -1 TEXT field
{
textEditor = new QTextEdit(parent);
textEditor->setObjectName("TextEditor");
return textEditor;
}
//000
// else
// {
// lineEditor = new QLineEdit(parent);
// lineEditor->setObjectName("LineEditor");
// return lineEditor;
// }
}
return QItemDelegate::createEditor(parent, option, index);
}
void MyDelegate::closeEditor ( QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
{
if(editor->objectName() == "ComboEditor")
removeEventFilter(this);
QItemDelegate::closeEditor(editor, hint);
}
void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
MySqlTableModel *m = (MySqlTableModel*)(index.model());
MyComboBox *comboBox;
QDateEdit *dateEdit;
QTextEdit *textEditor;
QLineEdit *le;
QString value;
double d;
if (m->isForeignKey(index.column()))
{
value = index.model()->data(index, Qt::DisplayRole).toString();
comboBox = static_cast<MyComboBox*>(editor);
comboBox->updateSearch(value);
(const_cast<MyDelegate*>(this))->setOldValue (value);
return;
}
switch ( m->getFieldType( index.column() ) )
{
case QVariant::Date:
value = index.model()->data(index, Qt::DisplayRole).toString();
dateEdit = static_cast<QDateEdit*>(editor);
dateEdit->setDisplayFormat("yyyy-MM-dd");
if (value != "") dateEdit->setDate(QDate::fromString(value, "yyyy-MM-dd"));
else dateEdit->setDate (QDate::currentDate());
// dateEdit->selectAll();
return;
case QVariant::String:
if ( m->getFieldLength( index.column() ) == -1 ) // if length=-1 - we have text field
{
value = index.model()->data(index, Qt::DisplayRole).toString();
textEditor = static_cast<QTextEdit*>(editor);
textEditor->setPlainText(value);
textEditor->selectAll();
return;
}
le = static_cast<QLineEdit*>(editor);
le->setText(index.model()->data(index, Qt::DisplayRole).toString());
le->selectAll();
return;
case QVariant::Double:
case QVariant::Int:
d = index.model()->data(index, Qt::DisplayRole).toDouble();
le = static_cast<QLineEdit*>(editor);
le->setText(QString("%1").arg(d));
le->selectAll();
return;
}
return QItemDelegate::setEditorData(editor, index);
}
void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
MySqlTableModel *m = (MySqlTableModel*)(index.model());
QTableView *v = static_cast<QTableView*>(editor->parent()->parent());
MyComboBox *comboBox;
QDateEdit *dateEdit;
QTextEdit *textEditor;
QLineEdit *lineEditor;
QString value;
if (m->isForeignKey(index.column()))
{
comboBox = static_cast<MyComboBox*>(editor);
value = comboBox->currentText();
if (comboBox->isInFullList(value) == TRUE)
model->setData(index, value);
else
{
QMessageBox::information(editor,"MyDB", "В списку немає такого значення!");
model->setData(index, oldValue);
}
// v->resizeColumnToContents(index.column());
return;
}
switch ( m->getFieldType( index.column() ) )
{
case QVariant::Date:
dateEdit = static_cast<QDateEdit*>(editor);
value = dateEdit->text();
model->setData(index, value);
return;
case QVariant::String:
if ( m->getFieldLength( index.column() ) == -1 ) // if length = -1 TEXT field
{
textEditor = static_cast<QTextEdit*>(editor);
value = textEditor->toPlainText();
model->setData(index, value);
return;
}
//000
// else
// {
// lineEditor = static_cast<QLineEdit*>(editor);
// value = lineEditor->text();
// model->setData(index, value);
// return;
// }
}
return QItemDelegate::setModelData(editor, model, index);
}
void MyDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
MySqlTableModel *m = (MySqlTableModel*)(index.model());
QWidget *w = static_cast<QWidget*>(editor->parent());
QRect r = option.rect;
// int h = w->size().height() - editor->rect().height()*index.row();
// r.setSize(QSize(200,(100 > h)?h:100));
// if ( m -> getFieldType( (index.column() ) == QVariant::String) && (m -> getFieldLength ( index.column() ) == -1 ) )
// editor->setGeometry(r); // for TEXT field (length == -1)
// else
editor->setGeometry(option.rect);
}
bool MyDelegate::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Return)
{
if (obj->objectName() == "ComboEditor")
{
MyComboBox *comboBox = static_cast<MyComboBox*>(obj);
if(comboBox->count() != 1)
{
comboBox->showPopup();
return true;
}
}
else
if(obj->objectName() == "TextEditor")
{
QTextEdit *textEdit = static_cast<QTextEdit*>(obj);
textEdit->insertPlainText("\n");
return true;
}
}
}
return QItemDelegate::eventFilter(obj, event);
}
Записан
Alexei
Гость
SqlTableModel/TableView тормоза
«
Ответ #3 :
Август 07, 2006, 08:08 »
Предлагаю следующее.
Сначала попробуй собрать проект в режиме release и выяснить на скольких записях повляются тормоза. Например, у меня в режиме release (без каких-либо своих делегатов) все шустро работает с количеством записей ~80000.
Затем потихоньку одну за одной подключай функции делегата.
И еще, что у тебя в MySqlTableModel::data(const QModelIndex& index, int role = Qt::DisplayRole)?
Записан
igorko
Гость
SqlTableModel/TableView тормоза
«
Ответ #4 :
Август 07, 2006, 10:04 »
Еще раз спасибо Alexei!
Я попробовал создать QSqlQueryModel/QTableView с таким же запросом и все работает быстро даже в режиме debug. Поэтому я думаю, что проблема в моей реализации.
Вот моя data:
QVariant MySqlTableModel::data (const QModelIndex & index, int role) const
{
if (!index.isValid())
return QVariant();
QSqlField field;
QString val;
QDate date;
int fieldNo = index.column();
if (hasPKey) fieldNo ++;
if (index.row() < query -> size ()) // index is in query size
{
if (updatedRecords.contains( index.row() ) ) // if index is in the updatedRecords
{
field = updatedRecords.value(index.row()).field( fieldNo );
}
else
if (query->seek(index.row()) == true) // if index is inside the query
{
field = query -> record().field( fieldNo );
}
}
else // if index is in the newRecords
if ( (index.row() - query->size() ) < newRecords.size() ) // !!!!!! CHECK <=
{
field = newRecords.value(index.row() - query->size() ).field( fieldNo );
}
switch (role)
{
case Qt::DisplayRole:
switch ( field.type() )
{
case QVariant::Double:
val.sprintf("%.2f",field.value().toDouble());
return val;
case QVariant::Date:
return field.value();
// date = QDate::fromString(field.value().toString(), "yyyy-MM-dd");
// return date.toString("dd.MM.yyyy");
}
return field.value().toString();
case Qt::TextAlignmentRole:
return (field.type() == QVariant::Double || field.type() == QVariant::Int) ?
QVariant(Qt::AlignRight | Qt::AlignVCenter)
: QVariant(Qt::AlignLeft | Qt::AlignVCenter);
}
return QVariant ();
}
Записан
Alexei
Гость
SqlTableModel/TableView тормоза
«
Ответ #5 :
Август 07, 2006, 10:53 »
field = query -> record().field( fieldNo);
Скорее всего, в этой строчке источник тормозов. Обращение query->record() - медленное, я уже сталкивался с этим.
Записан
igorko
Гость
SqlTableModel/TableView тормоза
«
Ответ #6 :
Август 07, 2006, 17:25 »
Скорее всего, Вы правы Alexei.
Большая часть "тормоза" убралась когда я убрал эту строчку.
Но как же мне заполнять модель из результата запроса без этой ф-ции?
По Вашим ответам видно, что Вы хорошо знакомы с темой.
Буду очень благодарен за хороший совет.
А то у меня аж руки опустились, когда увидел что и на Qt можно сделать то что невозможно использовать 8-|
Записан
Alexei
Гость
SqlTableModel/TableView тормоза
«
Ответ #7 :
Август 07, 2006, 20:21 »
Заполнять модель данными можно с помощью функции value() класса QSqlQuery, минуя вызов record(). Например, query->value(fieldNo).toString()
Остается сделать так, чтобы информация о поле была доступна внутри функции MySqlTableModel::data(). Функцию record() надо вызвать один раз сразу же после выполнения запроса:
query->exec(Тут стоит запрос);
rec = query.record(); //rec должен быть объявлен в классе MySqlTableModel
теперь rec можно использовать в функции data для получения информации о полях записи, а вот данные брать, как уже было упомянуто, с помощью query->value(индекс поля) без использования query->record()
Еще один момент. Возможно будет проще сделать MySqlTableModel наследником от QSqlQueryModel и функция data():
QVariant MySqlTableModel::data(const QModelIndex & index, int role) const
{
QVariant v = QSqlQueryModel::data(index, role);
//далее работать с переменной v
.....
}
В этом случае не понадобится переменная query, так как в классе QSqlQueryModel есть функция SetQuery(подробнее можно посмотреть в документайии по классу QSqlQueryModel)
Записан
bigirbis
Гость
SqlTableModel/TableView тормоза
«
Ответ #8 :
Август 08, 2006, 08:46 »
Цитировать
QSqlQuery q(query);
QStringList sl;
while (q.next())
sl += q.value(0).toString();
MyComboBox *comboEditor = new MyComboBox(sl, parent);
ИМХО, не стоит заполнять ComboBox так явно. Думаю для начала надо создать модель, а потом ее уже передать в ComboBox, т.о. источник данных будет общий.
Записан
Страниц: [
1
]
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...