Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

+1 199новых вакансий за сутки·93 838вакансий открыто сейчас·Новое:Talanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 273
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: фильтры с числами, отклик по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 409 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 222
  • Облачные технологии14 171
  • QA вакансии3 456
  • Backend вакансии2 114
  • Инженер данных1 801
  • Продакт-менеджер1 247

Разработка

  • Android1 858
  • iOS1 698
  • Fullstack вакансии997
  • AI вакансии955
  • Frontend вакансии755
  • Mobile вакансии44

По стеку

  • Go8 752
  • Java6 593
  • Node.js2 036
  • .NET1 739
  • Kotlin1 618
  • Rust1 472
  • C#717
  • PHP690
  • C++579

DevOps и инфраструктура

  • Kubernetes7 787
  • DevOps вакансии6 095
  • Linux-инфраструктура5 508
  • Terraform / IaC4 287
  • CI/CD3 272
  • Мониторинг и Observability1 792
  • SRE566
  • Кибербезопасность454

Аналитика и данные

  • Data Scientist1 138
  • Бизнес-аналитик921
  • Аналитик данных858
  • Системный аналитик154

Другие направления

  • Проджект-менеджер624
  • UI/UX дизайн149
  • Ручное тестирование14

По регионам

  • Вакансии в США44 166
  • Вакансии в Европе24 014
  • Вакансии в Канаде4 535
  • Работа в России3 867

По формату

  • Удалённые вакансии75 005
  • Релокация в США44 166
  • Гибридная работа12 485
  • Офисная работа7 090

По уровню

  • Senior вакансии42 643
  • Middle вакансии20 960
  • Junior вакансии6 708

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis38 вакансий
  • Spotify37 вакансий
  • Adyen29 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме QtВсе вопросы
QtMiddleТеория

Что такое классы model/view в Qt (QAbstractItemModel, QListView, QTableView)?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Model/View Qt разделяет данные (QAbstractItemModel) и отображение (QListView, QTableView). Кастомная модель реализует rowCount(), columnCount(), data() и сообщает об изменениях через beginInsertRows()/endInsertRows() и emit dataChanged().

Реализация кастомной модели

#include <QAbstractTableModel>
#include <QColor>
#include <vector>

struct Employee {
    QString name;
    int     salary;
};

class EmployeeModel : public QAbstractTableModel {
    Q_OBJECT
public:
    explicit EmployeeModel(QObject *parent = nullptr)
        : QAbstractTableModel(parent) {}

    // Обязательные методы
    int rowCount(const QModelIndex &parent = {}) const override {
        return parent.isValid() ? 0 : static_cast<int>(m_data.size());
    }

    int columnCount(const QModelIndex &parent = {}) const override {
        return parent.isValid() ? 0 : 2;
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override {
        if (!index.isValid()) return {};
        const auto &emp = m_data.at(index.row());
        if (role == Qt::DisplayRole) {
            return index.column() == 0 ? emp.name : QString::number(emp.salary);
        }
        if (role == Qt::BackgroundRole && emp.salary > 200000) {
            return QColor(Qt::yellow);  // выделить высокооплачиваемых
        }
        return {};
    }

    // Заголовки столбцов
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override {
        if (role != Qt::DisplayRole || orientation != Qt::Horizontal) return {};
        return section == 0 ? tr("Name") : tr("Salary");
    }

    // Редактируемая модель
    bool setData(const QModelIndex &index, const QVariant &value, int role) override {
        if (role != Qt::EditRole || !index.isValid()) return false;
        if (index.column() == 0) m_data[index.row()].name = value.toString();
        else m_data[index.row()].salary = value.toInt();
        emit dataChanged(index, index, {role});
        return true;
    }

    Qt::ItemFlags flags(const QModelIndex &index) const override {
        return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
    }

    // Добавление строк
    void addEmployee(const Employee &emp) {
        const int row = static_cast<int>(m_data.size());
        beginInsertRows({}, row, row);  // ОБЯЗАТЕЛЬНО перед изменением данных
        m_data.push_back(emp);
        endInsertRows();
    }

private:
    std::vector<Employee> m_data;
};

Архитектура Model/View в Qt

Qt реализует паттерн Model/View, разделяя данные (модель), их отображение (представление) и редактирование (делегат). Это позволяет использовать одну модель с несколькими представлениями одновременно, а также легко подменять источник данных без изменения UI.

Ключевые классы

  • QAbstractItemModel — базовый класс всех моделей; определяет интерфейс данных.
  • QAbstractListModel — упрощённая база для одномерных списков.
  • QAbstractTableModel — база для двумерных таблиц.
  • QStandardItemModel — готовая модель общего назначения (дерево, таблица, список).
  • QListView — отображает список (одна колонка).
  • QTableView — отображает таблицу (строки и колонки).
  • QTreeView — отображает иерархическое дерево.
  • QSortFilterProxyModel — прокси-модель для сортировки и фильтрации без изменения исходной модели.

Использование модели с представлениями

#include <QApplication>
#include <QTableView>
#include <QListView>
#include <QSortFilterProxyModel>
#include <QHeaderView>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    auto *model = new EmployeeModel;
    model->addEmployee({"Alice", 180000});
    model->addEmployee({"Bob",   250000});
    model->addEmployee({"Carol", 150000});

    // Прокси для сортировки — не трогает исходную модель
    auto *proxy = new QSortFilterProxyModel;
    proxy->setSourceModel(model);
    proxy->setFilterKeyColumn(0);          // фильтровать по колонке «Name»
    proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);

    QTableView tableView;
    tableView.setModel(proxy);
    tableView.setSortingEnabled(true);     // клик по заголовку сортирует
    tableView.horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    tableView.show();

    // Тот же model в listView (только первая колонка)
    QListView listView;
    listView.setModel(model);              // исходная модель, без прокси
    listView.show();

    return app.exec();
}

QModelIndex и иерархия

QModelIndex идентифицирует ячейку через тройку (row, column, internalPointer/internalId). Для плоских моделей parent() всегда возвращает невалидный индекс. Для деревьев internalPointer указывает на родительский узел.

Подводные камни

  • Отсутствие beginInsertRows/endInsertRows: изменение m_data без этих вызовов не уведомляет представления — данные обновятся, но UI останется пустым или с мусором.
  • dataChanged без правильного диапазона: если передать неверные индексы в emit dataChanged(), представление может не перерисоваться или перерисовать не те ячейки.
  • QStandardItemModel для больших данных: удобна, но медленна при тысячах строк — каждый QStandardItem — отдельный объект в куче. Для больших объёмов реализуйте кастомную модель.
  • rowCount с валидным parent: для плоских моделей rowCount должен возвращать 0, если parent.isValid(), иначе QTreeView воспримет каждую строку как узел с дочерними элементами.
  • Прямое удаление строк без beginRemoveRows: crash или UB, потому что представление хранит постоянные индексы.
  • Игнорирование роли в data(): реализация, которая возвращает данные только для DisplayRole, не поддерживает EditRole, ToolTipRole, SortRole — это ломает встроенные делегаты и прокси.
  • Хранение QModelIndex между операциями: после beginInsertRows/beginRemoveRows сохранённые индексы становятся невалидными; используйте QPersistentModelIndex если нужно хранить ссылку.

Типичные ошибки

  • Объяснять Qt model/view classes только по синтаксису, без жизненного цикла и стоимости.
  • Игнорировать ошибки, null/empty состояния, порядок инициализации или режим сборки.
  • Давать пример, который работает в демо, но ломается при изменении владельца ресурса.
  • Смешивать signals/slots с generic callbacks и забывать про thread affinity.

Что проверяет интервьюер

  • Кандидат формулирует точную модель для Qt model/view classes, а не только определение.
  • Пример компилируем, безопасен по lifetime и соответствует версии технологии.
  • Названы trade-off, ограничения и диагностируемые симптомы ошибки.
  • Понимает границу между C++ кодом, runtime/framework metadata и editor/UI слоем.

Как вы знаете этот вопрос?

Проверить себя по теме Qt →

Источники

  • https://doc.qt.io/qt-6/model-view-programming.html
←Предыдущий вопросКак соединять signals и slots в Qt 5 vs Qt 6 (синтаксис нового стиля)?Следующий вопрос→Что такое Qt Test framework и как писать unit-тесты?

Связанные темы

Qtobject-lifetimeperformance-debuggingui-architecture

Частые вопросы на собеседовании

  • Как Qt работает с многопоточностью? Что такое QThread и паттерн worker-object?
  • Как работает управление памятью в Qt?
  • В каких проектах Qt оправдан, а где он становится источником лишней сложности?
  • Что такое иерархия объектов Qt и как работает владение по принципу parent-child?