Evgenii Legotckoi
Evgenii LegotckoiҚар. 18, 2015, 10:14 Т.Ж.

Qt/C++ - 039-сабақ. QSqlTableModel жүйесінде жолды бағандағы мән бойынша бояу әдісі

Сабақта QSqlTableModel бағдарламасымен жұмыс істеу, SQL деректер қорынан деректер кестесін көрсету жан-жақты талқыланды. Бірақ оқырмандардың бірінің сұрағына байланысты мен осы мысалға шағын қосымша енгіземін.

Сұрақ бағандардың біріндегі мәнге байланысты бүкіл жолды қалай бояуға болады. QSqlTableModel -мен жұмыс істеу мысалында жолдар деректер қорына күні, уақыты, псевдокездейсоқ қосылды. нөмірі және осы жалған кездейсоқ сан туралы хабарлама. Осыған байланысты псевдокездейсоқ сан 41-ге тең болатын жолдар тәжірибелік сызықтар ретінде таңдалды.

Ол үшін QSqlTableModel сыныбынан мұра алу және QSqlTableModel::data() әдісін қайта анықтау қажет. Осыдан кейін деректер үлгісі ретінде жаңа мұрагер класын пайдаланыңыз.


tablemodel.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

tablemodel.cpp

Түпнұсқа мысалда 0-баған кестеде көрсетілмейтінін ескертемін, сондықтан біз деректерді 2-бағаннан емес, 3-бағаннан алуды таңдаймыз. Деректер базалық класс әдісін шақыру арқылы алынады.

#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();
}

Барлығы

Нәтиже – жолдар қызыл түске боялған кестені көрсететін қолданба, мұнда 41-ге тең жалған кездейсоқ сан бар. Сонымен қатар, бұл тәсіл сәйкесінше QAbstractItemModel. ішінен мұраланған барлық сыныптар үшін жарамды. QSqlQueryModel , QSqlRelationalTableModel т.б.

Ubuntu ОЖ астындағы сабақ үлгісімен мұрағат - DataBase сыныбында дерекқор файлы жасалған жолды мұқият тексеріңіз.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Юрий
  • Қаз. 8, 2017, 1:29 Т.Қ.

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

Evgenii Legotckoi
  • Қаз. 8, 2017, 2:37 Т.Қ.

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

Юрий
  • Қаз. 8, 2017, 3:20 Т.Қ.

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

Evgenii Legotckoi
  • Қаз. 8, 2017, 3:38 Т.Қ.

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

Юрий
  • Қаз. 8, 2017, 4:35 Т.Қ.

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

Evgenii Legotckoi
  • Қаз. 8, 2017, 4:44 Т.Қ.

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

Юрий
  • Қаз. 8, 2017, 5: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, 2017, 5:16 Т.Қ.

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

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

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

Evgenii Legotckoi
  • Қаз. 8, 2017, 5:38 Т.Қ.

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

Юрий
  • Қаз. 8, 2017, 5:46 Т.Қ.

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

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

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

Юрий
  • Қаз. 8, 2017, 6: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, 2017, 6:23 Т.Қ.

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

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

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

А потом как получить эту переменную?
Юрий
  • Қаз. 8, 2017, 9:10 Т.Қ.

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

k
  • Наурыз 23, 2018, 10:06 Т.Ж.

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

k
  • Наурыз 23, 2018, 10:41 Т.Ж.

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

МА
  • Мамыр 27, 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, 2020, 4:29 Т.Ж.

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

МА
  • Мамыр 28, 2020, 4:35 Т.Ж.
  • (өңделген)

del

МА
  • Мамыр 28, 2020, 4:35 Т.Ж.

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

Evgenii Legotckoi
  • Мамыр 28, 2020, 4: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();
            }
МА
  • Мамыр 28, 2020, 5:06 Т.Ж.

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

TableModel  *model = new TableModel(this);

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

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

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

Evgenii Legotckoi
  • Мамыр 28, 2020, 5:19 Т.Ж.

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

МА
  • Мамыр 28, 2020, 5:29 Т.Ж.

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

Evgenii Legotckoi
  • Мамыр 28, 2020, 5:35 Т.Ж.

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

МА
  • Мамыр 28, 2020, 8:09 Т.Ж.
 model->setData(model->index(1, 0), 7);

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

Evgenii Legotckoi
  • Мамыр 28, 2020, 4: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();

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

МА
  • Мамыр 28, 2020, 4:08 Т.Қ.

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

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

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

Evgenii Legotckoi
  • Мамыр 28, 2020, 4:14 Т.Қ.

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

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

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

МА
  • Мамыр 29, 2020, 7:27 Т.Ж.
            QModelIndexList rowIndexes = ui->tableView->selectionModel()->selectedRows();
            model->removeRows(rowIndexes.first().row(), rowIndexes.size());
            model->submitAll();
            model->select();

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

Evgenii Legotckoi
  • Мамыр 29, 2020, 7:30 Т.Ж.
  • (өңделген)

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

a
  • Жел. 11, 2022, 4:37 Т.Ж.

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

Evgenii Legotckoi
  • Жел. 12, 2022, 3: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, 2022, 9:06 Т.Ж.

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

Evgenii Legotckoi
  • Жел. 12, 2022, 9:12 Т.Ж.
  • (өңделген)

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз