Evgenii Legotckoi
Evgenii Legotckoi18. November 2015 10:14

Qt/C++ - Lektion 039. Wie male ich einen Strich in QSqlTableModel nach Wert in der Spalte?

In der Lektion zum Arbeiten mit QSqlTableModel wurde das Anzeigen einer Datentabelle aus der SQL -Datenbank ausführlich besprochen. Aber im Zusammenhang mit einer Frage eines Lesers mache ich eine kleine Ergänzung zu diesem Beispiel.

Die Frage war, wie die gesamte Zeile in Abhängigkeit vom Wert in einer der Spalten eingefärbt werden soll. Im Beispiel der Arbeit mit QSqlTableModel wurden Zeilen mit Datum, Uhrzeit und Pseudozufällen zur Datenbank hinzugefügt Nummer und eine Nachricht über diese Pseudo-Zufallszahl Nummer. In dieser Hinsicht wurden die Linien, bei denen die Pseudozufallszahl gleich 41 ist, als experimentelle Linien ausgewählt.

Dazu ist es notwendig, von der QSqlTableModel -Klasse zu erben und die QSqlTableModel::data()-Methode zu überschreiben. Danach verwenden Sie die neue Erbenklasse als Datenmodell.


Tabellenmodell.h

#ifndef TABLEMODEL_H
#define TABLEMODEL_H

#include <QObject>
#include <QSqlTableModel>

class TableModel : public QSqlTableModel
{
    Q_OBJECT
public:
    explicit TableModel(QObject *parent = 0);
    QVariant data(const QModelIndex &idx, int role) const;

signals:

public slots:
};

#endif // TABLEMODEL_H

Tabellenmodell.cpp

Ich stelle fest, dass im ursprünglichen Beispiel Spalte 0 nicht in der Tabelle angezeigt wird, also wählen wir, Daten aus Spalte 3 und nicht aus Spalte 2 zu erhalten. Daten werden durch Aufrufen der Basisklassenmethode abgerufen.

#include "tablemodel.h"
#include <QColor>

TableModel::TableModel(QObject *parent) : QSqlTableModel(parent)
{

}

QVariant TableModel::data(const QModelIndex &idx, int role) const
{
    if(role == Qt::BackgroundColorRole){
        if(QSqlTableModel::data(this->index(idx.row(), 3)).toInt() == 41){
            return QColor(Qt::red);
        }
    } else if(role == Qt::DisplayRole){
        return QSqlTableModel::data(idx);
    }
    return QVariant();
}

Insgesamt

Das Ergebnis ist eine Anwendung, die eine Tabelle anzeigt, in der Zeilen rot eingefärbt sind, wobei eine Pseudo-Zufallszahl gleich 41 ist. Außerdem gilt dieser Ansatz für alle Klassen, die jeweils von QAbstractItemModel geerbt werden QSqlQueryModel , QSqlRelationalTableModel usw.

Archiv mit einer Beispiellektion unter Ubuntu OS – Überprüfen Sie sorgfältig den Pfad, in dem die Datenbankdatei in der DataBase-Klasse erstellt wird.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Юрий
  • 8. Oktober 2017 13:29

Как передать переменную в класс наследник?

Evgenii Legotckoi
  • 8. Oktober 2017 14:37

А чутка подробнее ситуацию можете описать? Я не понял формулировки вопроса.

Юрий
  • 8. Oktober 2017 15:20

Я хочу из БД дергать значения цветов из профиля пользователя. Как мне передать user_id?

Evgenii Legotckoi
  • 8. Oktober 2017 15:38

То есть хотите подкрасить строку в таблице по цвету из профиля пользователя?

Юрий
  • 8. Oktober 2017 16:35

Да именно так. Но как передать id пользователя не знаю.

Evgenii Legotckoi
  • 8. Oktober 2017 16:44

Теоретически можно воспользоваться QSqlQuery, чтобы выдернуть данные из профиля прямо в методе data. А сам id можно дёрнуть через метод data, как взято значение в колонке через QSqlTableModel::data(this->index(idx.row(), 3)).toInt()

Юрий
  • 8. Oktober 2017 17:06

Так id пользователя нет в данной таблице.

qry->prepare("select * from users where  id=" + id_user);

colorstatus1 = qry->value("colorstatus1").toString();

Variant value = QSqlQueryModel::data(idx, role);
if(role == Qt::BackgroundColorRole)
{
    if (idx.sibling(idx.row(),6).data( Qt::DisplayRole ).toInt() == 1)
{
    return qVariantFromValue(QColor(colorstatus1));
}
Evgenii Legotckoi
  • 8. Oktober 2017 17:16

Ну я откуда знал, что у Вас нет этого id в таблице. И это разговор идёт про таблицу с профилями пользователей? Как тогда Вы делаете соответствие между пользователями и их данными, то есть цветами и т.д?

И вот этот код, что Вы привели, он вообще сработал?
Юрий
  • 8. Oktober 2017 17:24

Суть такая, есть таблица, в ней меняются статусы и соответственно цвет строк. В профиле пользователя настраивается эти цвета. Код не работает. В том то и проблема. Пользователь проходит аутентификацию и я получаю его id., а вот как мне передать это id. Сигналы и слоты в данном случае не подходят, я просто не знаю(((

Evgenii Legotckoi
  • 8. Oktober 2017 17:38

Так, хорошо. статусы меняются. То есть записываете состояние статуса в определённую таблицу... Но там же должен быть внешний ключ на пользователя? Если его нет, то сделайте внешний ключ на пользователя и тогда сможете без проблем дёргать статус и по нему прилагать нужный цвет. Обычно в таких случаях всегда в таблице профилей имеется внешний ключ на пользователя. Реляционные базы данных так и работают.

Юрий
  • 8. Oktober 2017 17:46

В профиле пользователя настраивается только интерфейс. В одной таблице работают несколько пользователей и все хотят что бы у них статусы били разными цветами(как раз настраивается в профиле).  Я записывал данные в файл настроек

 QSettings *settings = new QSettings( "settings.conf", QSettings::IniFormat );
    settings->beginGroup( "ColorStatus" );
    settings->setValue("colorstatus1", ui->lineEdit_colorstatus1->text());
и потом просто читал данные из файла. Просто хочу реализовать через БД.
Evgenii Legotckoi
  • 8. Oktober 2017 17:53

Ну понятно тогда. Сделайте тогда некую таблицу профилей вместо файла настроек, в которой будет храниться набор цветов для каждого варианта статуса. В таблице нужно создать несколько колонок, например четыре колонки для четырёх вариантов статуса. И обязательно внешний ключ на id пользователя. Когда пользователь аутентифицируется, то тогда можно будет дёрнуть через QSqlQuery, например, цвет статуса из таблицы профилей.

Юрий
  • 8. Oktober 2017 18:11

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

Можно как-то объявить переменную QString доступную из разных классов(форм или файлов .cpp)?

TableModel::TableModel(QObject *parent) : QSqlTableModel(parent)
{
    QSqlQuery *qry = new QSqlQuery();
    qry->prepare("select * from users where  id=" +id_user);
    if(qry->exec())
    { qry->next();
        colorstatus1 = qry->value("colorstatus1").toString();
    }
}
 
QVariant TableModel::data(const QModelIndex &idx, int role) const
{
    if(role == Qt::BackgroundColorRole){
      if (idx.sibling(idx.row(),6).data( Qt::DisplayRole ).toInt() == 1)
        {
            return qVariantFromValue(QColor(colorstatus1));
        }
    } else if(role == Qt::DisplayRole){
        return QSqlTableModel::data(idx);
    }
    return QVariant();
}
Evgenii Legotckoi
  • 8. Oktober 2017 18:23

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

Что вообще должна показывать эта самая TableModel? Список всех пользователей с их статусами?
Юрий
  • 8. Oktober 2017 18:41

Статусы ремонта. "Ждем запчасти", "Без ремонта" и т.д. Я объявляю  public: static QString id_user;

А потом как получить эту переменную?
Юрий
  • 8. Oktober 2017 21:10

Спасибо большое. Все разобрался))) Все оказалось  как всегда просто.

k
  • 23. März 2018 10:06

Почему-то при встраивании кода в урок 008, при редактировании строки, значения в виджетах пропадают и при сохранении изменений ничего не меняется. Где вызывается функция date?

k
  • 23. März 2018 10:41

Нашел ошибку. В функии data() в конце вместо QVariant(), вернул QSqlTableModel::data(idx,role). И все заработало!

МА
  • 27. Mai 2020 12:37

Вопрос- с переопределенным методом data и нашим классом- наследником- как удалять строки из модели?

            // Get all selections
            QModelIndexList indexes = ui->tableView->selectionModel()->selection().indexes();
            for (int i = 0; i < indexes.count(); ++i)
            {
                QModelIndex index = indexes.at(i);
                // To get the row/column numbers use index.row() / index.column()
                //qDebug() << "index.row() = " << index.row();
                model->removeRow(index.row());
                model->submitAll();
            }

метод model->removeRow(index.row());
не работает.

Evgenii Legotckoi
  • 28. Mai 2020 04:29

Для QSqlTableModel концептуально верным подходом являтся удаление запросом к базе данных.

МА
  • 28. Mai 2020 04:35
  • (bearbeitet)

del

Это как понять? Т.е. не через модель удалять, а через запрос к базе? А в чем тогда правильность? Если правильней с моделью работать, а не с базой в обход модели? Или я не так понял.

Evgenii Legotckoi
  • 28. Mai 2020 04:55

А. Да вы правы. Я немного попутал модель эту QSqlTableModel с QSqlQueryModel. У них есть разница, что QSqlQueryModel является read only, а поэтому функционал по удалению нужно дописывать.

Я думаю, всё дело в том, что или стратегия удаления не совсем верно настроена, либо там происходит какая-то ошибка.
Выведите в qDebug резальтат lastError() из модели. Там может быть по факту что угодно.

            QModelIndexList indexes = ui->tableView->selectionModel()->selection().indexes();
            for (int i = 0; i < indexes.count(); ++i)
            {
                QModelIndex index = indexes.at(i);
                // To get the row/column numbers use index.row() / index.column()
                //qDebug() << "index.row() = " << index.row();
                model->removeRow(index.row());
                model->submitAll();
                qDebug() << model->lastError();
            }

QSqlError("", "", "")
Причем, если я использую Ваш подход- наследованный класс

TableModel  *model = new TableModel(this);

то не удаляет, как только делаю родной класс:

QSqlTableModel  *model = new QSqlTableModel (this); // работает

То удаляет и ошибка:
QSqlError("", "", "")
такая же.

Evgenii Legotckoi
  • 28. Mai 2020 05:19

После работы гляну проект. Пока нет мыслей.

ок, буду ждать. Это странно, т.к. мы не переопределяли метод удаления.

Evgenii Legotckoi
  • 28. Mai 2020 05:35

Ну вот поэтому я и нахожусь в замешательстве. Вообще не должно было быть такого поведения. Разве что каким-то образом повлиял запрос в конструкторе, может быть не закрылась транзакция или что-то ещё, леший его знает.

МА
  • 28. Mai 2020 08:09
 model->setData(model->index(1, 0), 7);

Вот еще странность- не может сделать запись в уже имеющейся ячейке.
А в оригинальном пишет, но с глюком.

Evgenii Legotckoi
  • 28. Mai 2020 16:06

Да, метод data всё-таки влиял, я переписал его так и заработало удаление

QVariant TableModel::data(const QModelIndex &idx, int role) const
{
    if (role == Qt::BackgroundColorRole)
    {
        if (QSqlTableModel::data(this->index(idx.row(), 3)).toInt() == 1186278907)
        {
            return QColor(Qt::red);
        }
    }
    else if (role == Qt::DisplayRole)
    {
        return QSqlTableModel::data(idx, role);
    }
    return QSqlTableModel::data(idx, role);
}

Далее ваш код для удаления переписал иначе

QModelIndexList rowIndexes = ui->tableView->selectionModel()->selectedRows();
model->removeRows(rowIndexes.first().row(), rowIndexes.size());
model->submitAll();
model->select();

Это будет более эффективно

Спасибо, завтра првоерю. А

 model->setData(model->index(1, 0), 7);

Тоже заработало?

Evgenii Legotckoi
  • 28. Mai 2020 16:14

Ну в моём примере, который в статье сработало так

model->setData(model->index(1, 1), 7);

Поскольку model->index(1, 0) - это индекс колонки id, которая скрыта, поэтому без дополнительных настроек таблицы вы не увидите результата

            QModelIndexList rowIndexes = ui->tableView->selectionModel()->selectedRows();
            model->removeRows(rowIndexes.first().row(), rowIndexes.size());
            model->submitAll();
            model->select();

не работает. Вылетает с ошибкой.

Evgenii Legotckoi
  • 29. Mai 2020 07:30
  • (bearbeitet)

У меня работает. Исправлял в проекте, который приложен к статье.
А что происходит в вашем коде, с учётом места вызова этого кода, я знать не могу ;)
Дебажьте и добавляйте условия, которые обезопасят вызов кода

a
  • 11. Dezember 2022 04:37

Здравствуйте.
В Вашем примере в строке QSqlTableModel::data(this->index(idx.row(), 3))
3 - это индекс столбца. А есть ли возможность в данном случае как-то использовать имя столбца?

Evgenii Legotckoi
  • 12. Dezember 2022 03:40

Добрый день. Нет, данный метод оперирует целочисленными значениями, которые являются индексами столбца и строки, для создания объекта QModelIndex, по которому уже метод data возвращает значение в ячейке.
Если ваш вопрос касается читаемости кода, то в таком случае правильным решением будет создать enum для столбцов, который будет отображать фактическое имя столбца.

    enum EColumnNames
    {
        FIRST_COLUMN = 1,
        SECOND_COLUMN = 2,
        THIRD_COLUMN = 3
    };

    QSqlTableModel::data(this->index(idx.row(), EColumnNames::THIRD_COLUMN));

a
  • 12. Dezember 2022 09:06

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

Evgenii Legotckoi
  • 12. Dezember 2022 09:12
  • (bearbeitet)

В этом случае вижу только какой-нибудь костыль в стиле перебора по всем индексам в заголовке с помощью методу headerData .
То есть пройтись в for цикле пока не будет совпадения названия столбца, запомнить индекс, а потом уже использовать его в методе data. Но опять же, headerData по умолчанию возвращает название колонки, но если делать перевод и переназывать колонки, то это решение покажет свою костыльность во всей красе. Так что это скорее только усложнит поддержку приложения.

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
A
ALO1ZE19. Oktober 2024 08:19
Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken