Задать вопрос
Ответы пользователя по тегу Qt
  • C++/Qt5. Как принудительно передать окну фокус?

    vxblog
    @vxblog
    Инженер-программист
    Реагировать приложение начинает только после нажатия на него

    Потому что окно отображается, но находится не в фокусе ввода. В вашем случае, нужно отобразить окно, а затем принудительно передать ему фокус ввода.

    Посмотрите QWidget::setFocus.
    Ответ написан
    Комментировать
  • Как проще показать и редактировать список структур в таблице?

    vxblog
    @vxblog
    Инженер-программист
    Есть готовая модель. QStandardItemModel. Добавляете или удаляете строки привычными insertRows/removeRows. Устанавливаете данные с помощью setData. Привычно и всё уже реализовано.
    Ответ написан
    Комментировать
  • Почему сигнал ReadyRead() вызывается только один раз?

    vxblog
    @vxblog
    Инженер-программист
    Что ж, с вашего позволения, устрою небольшое code review.

    Установка параметров порта.
    Да, метод setPortName не возвращает ничего. Но, вызовы QSerialPort::setBaudRate, QSerialPort::setDataBits, QSerialPort::setParity, QSerialPort::setStopBits и QSerialPort::setFlowControl могут вернуть false. Пытаться открыть после этого порт явно не стоит. Лучше вызвать QSerialPort:error, чтобы обработать ошибку.

    Сигналы и слоты.
    1. Cоединить сигнал QSerialPort::readyRead со слотом ComPort::HandleReadyRead можно сразу после создания экземпляра QSerialPort. До установки параметров порта и его открытия.
    2. Однозначно, необходимо подключить сигнал QSerialPort::errorOccurred и реализовать обработку ошибок. Ну хотя бы их вывод в консоль во время отладки.
    3. Пожалуйста, не используйте макросы SIGNAL и SLOT. Переходите на функторы.


    QObject::connect (com_port_, &QSerialPort::readyRead, this, &ComPort::handleReadyRead);
    QObject::connect (com_port_, &QSerialPort::errorOccurred, this, &ComPort::handleError);


    Открытие порта.
    Метод QSerialPort::open следует вызывать только после успешной установки параметров порта (см. выше). И даже после этого он может вернуть false. В этом случае ничего не остаётся, как вызвать QSerialPort:error, чтобы отреагировать на ошибку. Кстати, это рекомендации из официальной документации.

    Чтение данных.
    Во-первых, метод чтения данных QSerialPort::read может вернуть -1 в случае ошибки. А метод QSerialPort::readAll в случае ошибки вернёт пустой QByteArray. Что нужно делать в этом случае? Правильно! Вызвать QSerialPort:error, чтобы отреагировать на ошибку.

    Во-вторых, я бы не стал полагаться на каждое срабатывание сигнала QSerialPort::readyRead, а использовал бы цикл с методом QIODevice::bytesAvailable, в котором считываются и обрабатываются все данные, о приходе которых стало известно по упомянутому выше сигналу.
    void ComPort::HandleReadyRead()
    {
      while (serial_->bytesAvailable () > 0) {
    
        // Чтение данных
        QByteArray data = serial_->readAll ();
        if (data.isEmpty ()) {
          handleError ();
          return;
        }
    
        read_buffer_.append (data);
    
        // Здесь ещё пристуствует логика обработки сообщения, я ищу символ конца
        // сообщения, и если его нахожу, то эмитирую сигнал, для вызова слота парсинга сообщения.
      }
    }


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

    Обработка ошибок.
    Простите, но у вас она отсутствует как класс. Реализуйте, например, предлагаемый мною ComPort::handleError.
    void ComPort::handleError (QSerialPort::SerialPortError error)
    {
      qDebug () << __LINE__ << __FUNCTION__ << error;
    }


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