Ответы пользователя по тегу Qt
  • Какую архитектуру выбрать для программы на Qt?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Я бы посоветовал:
    • Не делать главный класс окна божественным объектом. Его нужно разделить на контролы-модули с их собственной кастомной логикой, валидацией и прочим, а связать между собой - сигналами и слотами.
    • Отделять бизнес-логику от интерфейса. Для чего использовать внедрение зависимостей и абстрактные (чисто виртуальные) классы для декларирования API.


    Допустим, парсером парсится конфиг в объект настроек, эти настройки передаются в фабрику, которая с оглядкой на них будет выдавать правильно сконфигурированные объекты по запросу. Ссылка на фабрику передается в класс окна, откуда добываются зависимости и передаются дальше контролам по ссылке. Контролы, получая зависимость (допустим, через конструктор), привязываются к ней через сигналы/слоты или непосредственно вызывают виртуальные методы.

    Итог: интерфейс декомпозирован, о бизнес-логике он не знает ничего, кроме предоставленного абстрактного API. Контролы знают друг о друге только в рамках сигналов/слотов между собой и списка зависимостей своих детей. Бизнес-логика не знает ничего об интерфейсе.
    Ответ написан
  • Qt Widgets: как обратить внимание на элемент управления?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Можно банально задать бордер через QSS:

    pWgt->setStyleSheet("border: 1px solid red");
    Ответ написан
  • Как понять почему падает Qt программа?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Логгирование.
    Ответ написан
  • Самый простой способ вызова функции в QT?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Наследование стоит применять тогда, когда вам нужен доступ к состоянию и детальным событиям. Для обработки нажатия достаточно прицепить ваш обработчик на сигнал QPushButton::clicked:

    auto btn = new QPushButton("click me!");
    
    QObject::connect(btn, &QPushButton::clicked, []() { 
    // создание диалога и вызов его в модальном режиме (через QDialog::exec)
    });
    //-----------------------------------
    void myFoo() { }
    
    auto btn = new QPushButton("click me!");
    QObject::connect(btn, &QPushButton::clicked, myFoo);

    UPD: В вашем случае можно сделать примерно так:
    auto btn = new QPushButton("click me!");
    
    QObject::connect(btn, &QPushButton::clicked, []() { 
        ::updateTable(table);
    });
    Ответ написан
  • Как правильно выводить информацию из QVector?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Откройте для себя Model/View в Qt. В частности, ваша задачка с каталогами описана здесь.

    Вкратце: у вас есть модель, в котором вы связываете ваш способ хранения (QVector в вашем случае) со стандарным интерфейсомQAbstractItemModel (или его потомки QAbstractListModel, QAbstractTableModel или QAbstractTreeModel), который можно передать в один из стандартных вью-виджетов (QListView, QTableView, QTreeView). Реализовав интерфейс (переопределив виртуальные методы data и setData для role==Qt::DisplayRole и Qt::EditRole), вы можете просто изменять состояние модели, а вью-виджеты подхватят изменения автоматически.

    Кроме того, есть еще такая штука - QDataWidgetMapper. Он умеет привязывать виджеты (даже обычные, не View) к определенным полям в модели.
    Пример

    Пример объемный, но минимально полный, содержащий всю необходимую инфраструктуру. Допустим, мы хотим создать редактор для некоторых статей (блога?). Нам нужен простой класс Article, чтобы собрать в кучу данные о каждой отдельной статье:

    class Article
    {
    public:
        Article(int id, const QString& title, const QString& content) 
            : _id(id), _title(title), _content(content) {}
    
        int id() const { return _id; } 
        void setId(int id) { _id = id; }
    
        QString title() const { return _title; } 
        void setTitle(const QString& title) { _title = title; }
    
        QString content() const { return _content; }
        void setContent(const QString& content) { _content = content; }
    
    private:
        int     _id;
        QString _title;
        QString _content;
    };

    Для него напишем модель хранения этих статей - ArticlesModel, содержащей массив статей и методы для их добавления/удаления. Кроме того, для нее мы реализуем стандартный интерфейс QAbstractTableModel (методы rowCount, columnCount, data и setData), чтобы виджеты знали, как оттуда брать и как обновлять данные.

    class ArticlesModel :
            public QAbstractTableModel
    {
    public:
        ArticlesModel(QObject *parent=nullptr);
    
        void addArticle(const Article& art);
        void removeArticle(int id);
    
        //QAbstractTableModel interface implamentation
        int rowCount(const QModelIndex &/*parent*/) const override;
        int columnCount(const QModelIndex &/*parent*/) const override;
    
        bool data(QModelIndex& index, const QVariant &value, int role) const override;
        QVariant setData(QModelIndex& index, int role) override;
        
    private:
        std::vector<Article> _articles;
    };
    
    // =================================================================
    
    ArticlesModel(QObject *parent/*=nullptr*/) 
        : QAbstractTableModel(parent)
    {
    }
    
    void ArticlesModel::addArticle(const Article& art) {
        _articles.push_back(art);
    }
    void ArticlesModel::removeArticle(int id) {
        auto found = std::find_if(begin(_articles), end(_articles), 
                                [id](const Article& art) {
                                    art.id() == id;
                                });
        if (found != std::end(_articles)) {
            _articles.erase(artIt);
        }
    }
    
    
    int ArticlesModel::rowCount(const QModelIndex &/*parent*/) const override {
        return _articles.size();
    }
    int ArticlesModel::columnCount(const QModelIndex &/*parent*/) const override {
        return 2;
    }
    
    bool ArticlesModel::data(QModelIndex& index, const QVariant &value, int role) const override {
        if (!index.isValid) return QVariant();
    
        if (role == Qt::EditRole) {
            switch (column) {
                case 0: 
                    QVariant(_articles[index.row()].setTitle(value.toString()));
                    return true; 
                case 1:
                    QVariant(_articles[index.row()].setContent(value.toString()));
                    return true; 
            }
        }
        return false;
    }
    
    QVariant ArticlesModel::setData(QModelIndex& index, int role) override {
        if (!index.isValid) return QVariant();
    
        if (role == Qt::DisplayRole || role == Qt::EditRole) {
            switch (column) {
                case 0: return QVariant(_articles[index.row()].title()); 
                case 1: return QVariant(_articles[index.row()].content());
            }
        }
        return QVariant();
    }


    Тогда можно сделать так:

    // this - это какой-то родительский виджет
    
    auto titleEditor = new QLineEdit(this);
    auto contentEditor = new QTextEdit(this);
    
    QAbstractTableModel *model = new ArticlesModel(this);
    model->addArticle(Article(1, "Hello title", "Hello content"));
    model->addArticle(Article(2, "Another title", "Another content"));
    
    auto mapper = new QDataWidgetMapper(this);
    mapper->setModel(model);
    mapper->addMapping(titleEditor, 0);
    mapper->addMapping(contentEditor, 1);
    mapper->toFirst(); // Переключаемся на первый элемент модели


    Теперь мы можем добавлять/удалять статьи в model->add/removeArticle(const Article&), переходить с заметки на заметку с помощью mapper->setCurrentIndex(int index), менять содержимое заметок в редакторе.

    Можно добавить QListView, так же передать туда модель через setModel() и связать сигнал изменения текущего элемента списка с тем же действием mapper, добавить пару кнопок для добавления/удаления заметок и мы получим полноценный редактор.
    Ответ написан
  • Почему константное значение Qstring?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Есть такое правило: "const по умолчанию", т.е. const нужно использовать везде, где это возможно. В данном случае QString передается по ссылке и планируется только для чтения, потому его делают константным.

    Кроме того, для копируемых объектов const не нужно, достаточно передавать их по значению (аргумент скопируется и нам будет доступна лишь его копия). Но QString может быть достаточно крупным, а вызовы метода - достаточно частыми, потому передается просто ссылка. Появляется возможность изменить объект через эту ссылку. Чтобы это снова запретить, в методе указывают const для аргумента-ссылки.
    Ответ написан
  • Как сделать Qt static?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Платиновый вопрос.

    1. Как это сделать?

    Сделать это можно собрав Qt из исходников с необходимыми ключами конфигурации. Руководств в сети много.

    2. Почему вообще это требуется делать?

    Делать этого не требуется в общем случае. Вам необходимо просто собрать бинарные версии библиотек (dll) в папке рядом с вашим исполняемым файлом (одна из них - модуль Qt5Widgets.dll, о которой вам говорит ошибка). Это динамическая линковка библиотек.

    Для удобства вы всегда можете воспользоваться windeployqt (для Windows), который соберет все необходимые файлы в одно место или просто отыскав и сложив их вручную (проанализировав зависимости процесса под отладкой в IDE с помощью Process Explorer или специальной утилитой - DependencyWalker)

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

    Ну и статическая линковка при прочих равных нарушает community-лицензию Qt, если с программой не распространять открытый исходный код (нужно дать возможность пользователю заменить версию Qt динамически, либо собрать программу с ним заново).
    Ответ написан
  • Как правильно написать системные требования к приложению?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Под "приложением" понимается релизный билд, верно?

    ОС - опирайтесь на используемый Qt
    Процессор - опирайтесь на используемый компилятор
    Оперативная память - диспетчер задач
    Видеоадаптер - поддержка OpenGL?
    Место на Ж/Д - размер релизного билда + некоторый минимально-реальный запас на логи и прочее сохраняемое.

    Это минимальные. Для рекомендуемых накиньте 30% для оперативки и постоянной памяти, ОС назовите ту, на которой тестировали.
    Ответ написан
  • Как сформировать корректный http запрос в qt?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    RFC:
    Request-URI = "*" | absoluteURI | abs_path | authority

    В переводе на русский: да, абсолютный путь (с хостом) в Request-URI допускается. А заголовок Host обязателен все равно.
    Ответ написан
  • Ошибка: no matching constructor for initialization, что делать?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Возможно, в конструкторе копирования потерялся const.
    TemplateRequirement(const TemplateRequirement &);
    Ответ написан
  • Как собрать MySQL для Qt под Андроид?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Зачем собирать MySQL, когда есть плагин QMYSQL ?
    Ответ написан