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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как вносить изменения в QTableView  (Прочитано 12221 раз)
kharkov_max
Гость
« : Май 17, 2013, 08:45 »

День добрый.
Прошу сразу не пинать с Qt только начинаю разбираться.

Пишу небольшую программку, программа работает с БД postgresql.
При помощи QTableView вывожу таблицу на форму.
Код:
void MdiWidget::createMdi()
{
    isUntitled = true;
    setWindowTitle(trUtf8("Table1"));
    showMaximized();

    QSqlDatabase db = QSqlDatabase::database("mydb");
    QSqlTableModel *model = new QSqlTableModel(0,db);
        model->setTable("books");
        model->setEditStrategy(QSqlTableModel::OnFieldChange);
        model->select();
        model->removeColumn(0); // don't show the ID
        model->setHeaderData(0, Qt::Horizontal, QObject::trUtf8("Строка"));
        model->setHeaderData(1, Qt::Horizontal, QObject::trUtf8("Строка2"));
        model->setHeaderData(2, Qt::Horizontal, QObject::trUtf8("Дата"));
    QTableView *view = new QTableView();
        view->setModel(model);
        view->setAlternatingRowColors(true);         // Подсветка строк разными цветами
        view->resizeRowsToContents();
        view->resizeColumnsToContents();
        view->setSortingEnabled(true);               // Сортировка таблицы
        view->sortByColumn(1,Qt::AscendingOrder);    // Порядок сортировки по умолчанию
        // view->show();
    QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(view);
        layout->setContentsMargins(0,0,0,0);
        this->setLayout(layout);
}

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

Скорее всего я что то не дочитал, подскажите как правильно.

Таблица выводится в MDIWindow.
Спасибо.
Записан
Flass
Гость
« Ответ #1 : Май 17, 2013, 10:11 »

Дорогой друг, боюсь что ты не дочитал ассистант, ибо вьюха эта не имеет собственной модели, поэтому ей данные хранить негде. Возможно ты хотел использовать QSqlTableView?
В любом случае, если ты будешь использовать простую вьюху с моделью, тебе еще надо будет сохранить данные из модели в базу. Запросами, например. Как самое простое. Или наполнять объект данными и сохранять его через драйвер.


Возможно я тебя просто не понял?

Запусти пожалуйста QtCreator. Нажми сочетание клавиш "Ctrl" и "7"
Веди слева в разделе указатель:  QSqlTableView
Почитай, то ли тебе надо?
« Последнее редактирование: Май 17, 2013, 10:16 от Flass » Записан
Bepec
Гость
« Ответ #2 : Май 17, 2013, 12:33 »

Предыдущий ответ какой то бредовый. Или в Qt 5.* появился такой компонент? Помоему это бред Flass.

Пара вопросов автору темы

1) этот код нерабочий. Скажем так, вероятно в настройках по дефолту у вас стоит postgresql. Я к сожалению незнаю Подмигивающий

Вот рабочий код
Код:
	QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("mydatabase.sqlite");
bool b = db.open();
qDebug() << db.lastError().text();
QSqlTableModel *model = new QSqlTableModel(0,db);
model->setTable("temp");
// model->setEditStrategy(QSqlTableModel::OnFieldChange);
model->select();
// закомменчено из-за того, что у меня кодировка файла windows 1251 и нет нужды скрывать первую колонку
/* model->removeColumn(0); // don't show the ID
model->setHeaderData(0, Qt::Horizontal, QObject::trUtf8("Строка"));
model->setHeaderData(1, Qt::Horizontal, QObject::trUtf8("Строка2"));
model->setHeaderData(2, Qt::Horizontal, QObject::trUtf8("Дата"));*/

// тут я использую выложенную на форму в дизайнере таблицу
QTableView *view = ui.tableView;
view->setModel(model);
view->setAlternatingRowColors(true);         // Подсветка строк разными цветами
view->resizeRowsToContents();
view->resizeColumnsToContents();
view->setSortingEnabled(true);               // Сортировка таблицы
view->sortByColumn(1,Qt::AscendingOrder);    // Порядок сортировки по умолчанию


PS вполне возможно вы уже инициировали базу где то в другом месте, но кода нет, а на нет и суда нет.
« Последнее редактирование: Май 17, 2013, 12:38 от Bepec » Записан
kharkov_max
Гость
« Ответ #3 : Май 17, 2013, 15:21 »

Да база PostgreSql, коннект инициируется такой функцией.

Код:
// Функция коннектор к базе данных
bool Connect_database::createConnection() {
    int database_port;
    bool database_ssl;
    QString conf_file,database_host,database_name,database_user,database_password,database_ssl_string;
    conf_file="ini\\settings.conf";

    // Подключаемся к базе данных спараметрами из файла конфигурации
    QSettings * settings = new QSettings(conf_file,QSettings::IniFormat);
        database_host = settings->value("database/host").toString();
        database_port = settings->value("database/port").toInt();
        database_name = settings->value("database/namedatabase").toString();
        database_user = settings->value("database/user").toString();
        database_password = settings->value("database/password").toString();
        database_ssl = settings->value("database/ssl").toBool();

    if (database_ssl == false) database_ssl_string="requiressl=0";
    if (database_ssl == true) database_ssl_string="requiressl=1";

    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL","mydb");
        db.setHostName(database_host);
        db.setPort(database_port);
        db.setDatabaseName(database_name);
        db.setUserName(database_user);
        db.setPassword(database_password);
        db.setConnectOptions(database_ssl_string);

    // Проверяем доступ к базе данных, если нет - выдаем ошибку пользователю и в консоль дебагера
    if (!db.open()){
        qDebug() << QObject::tr("Не возможно подключится к базе данных") << db.lastError().text();
        QMessageBox::critical(0,QObject::tr("Ошибка подключения к базе данных"),
                              QObject::tr("Проверте настройки подключения в файле ini\\settings.conf"),
                              db.lastError().text());
        return false;
    }
    return true;
}

Инициируется при открытии MainWindow
Код:
MainWindow::MainWindow (QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    mdiArea = new QMdiArea;
    mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    setCentralWidget(mdiArea);
    createStatusBar();

    Connect_database *connect = new Connect_database;
        if (!connect->loockconfig()) return;
        if (connect->createConnection() != true) return;
}

Т.е. QSqlDatabase db = QSqlDatabase::database("mydb"); это уже вызов открытого подключения, ну и далее по смыслу.
Записан
Bepec
Гость
« Ответ #4 : Май 17, 2013, 17:16 »

Ну выдерните строки из моего предыдущего сообщения и присобачьте к своему проекту. Заработает - хорошо. Не заработает - плохо.
Записан
kharkov_max
Гость
« Ответ #5 : Май 17, 2013, 18:37 »

Ну выдерните строки из моего предыдущего сообщения и присобачьте к своему проекту. Заработает - хорошо. Не заработает - плохо.

Извините, конечно, может я что то не вижу, но чем Ваш код отличается от моего ?

Моя таблица дожна выводится в MDI и QVBoxLayout...
Записан
Bepec
Гость
« Ответ #6 : Май 17, 2013, 18:53 »

Кхм. Если вы не можете разглядеть отличия, мб не стоит заводить тогда тему?

Изменено около 3 строк.
Закоммичено около 4 строк.

Вместо использования уже инициализированной базы, база заново открывается.

Это основные различия. Так же используется таблица на форме (не обязательно, но для тестового проекта удобнее).

К тому же закомментирована стратегия редактирования базы. Почему то с разкометированной стратегией, таблица начинала себя вести чрезвычайно странно, дублируя введённые надписи в нескольких строках.

PS пробовать надо ТЕСТОВЫЙ проект. Создали, накидали на форму, базу подрубили и проверили. Работает - круто. Не работает - ищем ошибку. Вместо сотен строк, у нас  имеется 10-15 строк с проблемой. Найти и локализовать ошибку проще.
Записан
kharkov_max
Гость
« Ответ #7 : Май 17, 2013, 19:12 »

Ну зачем же так жестоко, это же дискуссия, тем более я не опытен. )))

Внял Вашему совету и посмотрел в сторону Ваших коментов в коде.
Сильно урезать свой код не стал, но все заработало когда привел свой код к такому виду

Вместо
Код:
        model->removeColumn(0); // don't show the ID
        model->setHeaderData(0, Qt::Horizontal, QObject::trUtf8("Строка"));
        model->setHeaderData(1, Qt::Horizontal, QObject::trUtf8("Строка2"));
        model->setHeaderData(2, Qt::Horizontal, QObject::trUtf8("Дата"));

Сделал
Код:
//        model->removeColumn(0); // don't show the ID
        model->setHeaderData(1, Qt::Horizontal, QObject::trUtf8("Строка"));
        model->setHeaderData(2, Qt::Horizontal, QObject::trUtf8("Строка2"));
        model->setHeaderData(3, Qt::Horizontal, QObject::trUtf8("Дата"));

Данные через форму начали меняться в таблице, но (естесственно) стало видно первый столбец id.

Возникло пару вопросов:
1. Для понимания, почему так происходит, если возможно, можете на пальцах объяснить?
2. Как скрыть на форме, в данной ситуации, столбец 0 (id)?

Еще раз заранее спасибо.
Записан
kharkov_max
Гость
« Ответ #8 : Май 17, 2013, 20:26 »

Отвечу ))

1. В модели так не может быть в принципе т.к. противоречит обновлению БД
Т.е. если скрываем столбец в модели то данные только для просмотра или потом програмно обновлять.
Возможно я тут в чем то заблуждаюсь ...

2. Что бы скрыть столбец, его нужно скрывать не в модели а в представлении QTableView
Как то так:
Код:
    QTableView *view = new QTableView();
        view->setModel(model);
        view->setColumnHidden(0,true);
        .......

Тогда и столбец индекса скрыт и данные обновляются.
Записан
Bepec
Гость
« Ответ #9 : Май 17, 2013, 21:03 »

Идеально Улыбающийся Вы молодец.

Модель жёстко связана с таблицей в базе данных. Любая операция с моделью отражается на базе.

Отображение же view может быть изменено как вы хотите Подмигивающий

В принципе это решение любых проблем:

1) Локализовать проблему до необходимого функционала.

2) Убирать по одному элементу до достижения желаемого результата.

3) Решить проблему.

PS мб я ошибаюсь, но вы должны гордиться тем, что разобрались сами Улыбающийся И это верно!!!

PPS извиняюсь если мой комментарий вас обидел или задел. 
« Последнее редактирование: Май 17, 2013, 21:06 от Bepec » Записан
kharkov_max
Гость
« Ответ #10 : Май 17, 2013, 21:31 »

Ну чего же обижаться, это же дискуссия. )))

Иногда из поста человека не совсем понятно что он имел ввиду.
Я и задавал свой "глупый" вопрос, т.к. вроде все у меня очевидно и должно работать и сильного отличия от Вашего кода не нашел. Ну да ладно, я только учусь и Ваш совет был в тему...

У меня вот есть другой вопрос.
Представим что есть таблица из 1000 столбцов и 10000 строк (это к примеру), ну очень большая таблица.
Мы хотим использовать модель и предстваление и отображать из этой таблицы на форме только 10 колонок.
Выбираем всю таблицу сразу - это условие.

Вопрос.
Кто скушает память у клиентского ПК, модель 1000*10000*(на объем данных) или представление 10*10000*(на объем данных) ?

Мой вопрос из области понимания оптимизации вывода данных и занимаемого объема ОЗУ.
Ну какая-то такая получается формулировка ...
Записан
Bepec
Гость
« Ответ #11 : Май 17, 2013, 21:48 »

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

1) в твоём случае память будет съедена моделью. Потому что данные загруженные сразу хранятся в ней.

2) model-View архитектура призвана решить  проблему с отображением. Ресурсы в View тратятся только на отображение видимых на экране элементов.

Не проверял, но если развернуть окно полностью, т.е. чтобы были видны все строки и столбцы, тогда наверно view загрузит память почище модели. Но это уже, скажем, высосанный из пальца случай.

3) модели Qt для отображения SQL данных не предназначена для работы с большими массивами данных. Таблицу в 8 млн записей с 5 столбцами они переварить не могут :/


Т.е.

Размер модели = размер данных.

Размер View = размер одного элемента * количество элементов на экране.

А теперь маленькое но.
Загрузка всех данных сразу - неразумное решение Подмигивающий Ибо средняя таблица забьёт всю память только на хранение.

НО!
Но время запроса к базе данных близится к нулю. Время запроса данных по отношению к отображению данных примерно 1% к 100%.

У меня остались наработки способные "скользить" по базе данных, необработанные напильником. Надо бы допилить, но не хватает времени и мотивации (стандартная отговорка Улыбающийся ).
« Последнее редактирование: Май 17, 2013, 21:52 от Bepec » Записан
Flass
Гость
« Ответ #12 : Май 20, 2013, 09:23 »

Предыдущий ответ какой то бредовый. Или в Qt 5.* появился такой компонент? Помоему это бред Flass.
Извините, перечитал, действительно чушь написал.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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