Squeak.ru - шаблоны программирования

Qt5-QML: как обрабатывать поле со списком в QML через JavaScript

Я получаю доступ к своим роботам через Wi-Fi, используя сторонний маршрутизатор. Я написал небольшое приложение, которое автоматически входит в маршрутизатор, перемещается по tab интерфейсу маршрутизатора, используя JavaScript внутри QML приложения. Небольшая проблема, с которой я столкнулся, заключается в том, что мне нужно активировать реле для включения/выключения робота, а в графическом интерфейсе маршрутизатора мне нужно активировать combobox, как показано на экране печати ниже. После нажатия на вкладку I/O адрес страницы роутера будет https://123.456.789.123:7878/admin/ACEmanagerX.html#:

реально

Соответствующий html также показан ниже:

html

РЕДАКТИРОВАНИЕ

Теперь, чтобы воспроизвести проблему, я развернул очень маленький веб-сайт https://comboboxtest.netlify.com/, который содержит только один список со списком с тем же именем и тем же выбором, который я пытаюсь вызвать.

Проблема в том, что я не могу найти простой способ включить или выключить реле.

Ожидаемое поведение будет таким: если это OFF (значение 0), поставьте его ON (значение 1, которое означает низкий уровень активности диска) и наоборот.

Если вы скопируете/вставите приведенный ниже код и запустите его, он автоматически откроет веб-сайт, но, к сожалению, он не изменит поле со списком с позиции OFF на Drive Active Low и наоборот.

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtWebEngine 1.9

ApplicationWindow{
    id: root
    width: 1940
    height: 1100
    visible: true
    property string cBox: "https://comboboxtest.netlify.com"
    QtObject {
        // Below property triggers the combo box of the relays evaluating the normally closed (NC) or
        // normally opened (NO) circuit
        property string get_normallyClosed_or_normallyOpened_comboBox: "
            var comboBox = document.getElementsByName('859-2-2')[0];
            comboBox.addEventListener('change', function (e) {
                comboBox.options[0].selected = true;
                if ('createEvent' in document) {
                    var evt = document.createEvent('HTMLEvents');
                    evt.initEvent('change', false, true);
                    sel.dispatchEvent(evt);
                }
                else {
                    sel.fireEvent('onchange');
                }
            });
            sel.addEventListener('change', function (e) {
            alert('changed');
            });
        ".arg(cBox)
    }

    Timer {
         id: timer
         interval: 1000; repeat: false
         onTriggered: view.runJavaScript(internals.get_normallyClosed_or_normallyOpened_comboBox)
        }

        WebEngineView {
            id: view
            anchors.fill: parent
            onUrlChanged: {
                console.log(url)
                if(url === Qt.resolvedUrl("https://comboboxtest.netlify.com/"))
                    timer.running = true
            }
            onCertificateError: function(error) {
                error.ignoreCertificateError();
            }
            Component.onCompleted: view.url = "https://comboboxtest.netlify.com"
        }
}

Что я уже пробовал

1) После прохождения этот пост Я выяснил, что очень важно дать время для запуска http запроса. Вот почему я добавил interval: 20000 после входа на вкладку I/O. Однако это не помогло, и поле со списком не сработало.

2) я использовал этот источник чтобы помочь мне понять, как вызвать поле со списком через JavaScript, и это именно то, что я применил, но я не видел никаких изменений в поле со списком.

3) я нашел этот пост что очень близко к тому, что я делаю, с той разницей, что здесь также использовалось Button для запуска поля со списком. Но в моем случае у меня нет кнопки.

Я знаю, что я близок к тому, чтобы это сработало, но есть кое-что, чего мне не хватает. Спасибо, что пролили свет на этот вопрос для решения проблемы

20.11.2019

  • Некоторые моменты... во-первых, вы смешиваете несколько несвязанных проблем в один вопрос/проблему, с которыми было бы легче справиться по отдельности. Во-вторых, ваш MRE не один, так как есть очевидные ошибки и недостающие части, плюс нет возможности воссоздать это без написания пользовательской HTML-страницы. Трудно сказать, что является настоящей ошибкой, а что просто вырезанным материалом. Я вижу кучу возможных проблем, наиболее очевидная из которых заключается в том, что document.getElementById('859-2-2') не будет работать, так как нет элемента с таким идентификатором — это элемент name. Используйте document.getElementsByName('859-2-2')[0]. 21.11.2019
  • См. stackoverflow.com/questions/51810358/ для программного выхода из приложения из QML. 21.11.2019
  • @MaximPaperno, спасибо, что прочитали вопрос. Я обновил вопрос о том, как обращаться со списком через JavaScript, и напишу отдельный вопрос для второй части. 21.11.2019
  • @MaximPaperno, я попробовал модификацию document.getElementsByName('859-2-2')[0];, но по-прежнему не вижу изменений в срабатывании поля со списком. Что мне не хватает в функции JavaScript, чего я не вижу? 21.11.2019
  • Ну... вы получаете ошибки... предупреждения? Что-нибудь в консоли вывода? Вы знаете, где он умирает? Типа... срабатывает ли time3? console.log() немного отладочной информации со стороны QML и JS. А что делает .arg(cBox)? Я не вижу заполнителя в тексте. Всегда убедитесь, что вы просматриваете вывод консоли во время тестирования кода, там может быть много полезных предупреждений. (В QtCreator это означает просмотр выходных данных приложения для C++ или общих сообщений для qmlscene.) 21.11.2019
  • @MaximPaperno, следуя вашему совету, я сделал это, чтобы упростить вопрос: я создал и развернул небольшой веб-сайт https://comboboxtest.netlify.com/ и пересмотрел опубликованный мной код. есть раздел РЕДАКТИРОВАНИЕ, который, как мне кажется, теперь стал проще. Теперь, если вы запустите именно этот код, он автоматически откроет веб-сайт, но, к сожалению, он по-прежнему не вызывает поле со списком. Также есть возможность inspect the element и посмотреть html страницу 21.11.2019

Ответы:


1

Я придумал для вас рабочий пример. На самом деле здесь нет ничего сложного, просто точный синтаксис, изучение JavaScript и особенно внимание к предупреждающим сообщениям, которые Qt выдает во время работы. Я не могу не подчеркнуть последнее — если вы не видите вывод консоли, это даже не стоит тестировать. Даже последний очищенный MRE генерировал предупреждения консоли, которые были легко устранены, после чего реальные проблемы стали более очевидными.

Есть два основных изменения. Сначала тест на

if (url === Qt.resolvedUrl("https://comboboxtest.netlify.com/"))

никогда не был true. Довольно простой и легко определяется с помощью console.log(). Хороший способ сравнить URL со строкой — использовать url.toString().

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

import QtQuick 2.13
import QtQuick.Controls 2.13
import QtWebEngine 1.9

ApplicationWindow{
  id: root
  width: 320
  height: 200
  visible: true
  property string url: "https://comboboxtest.netlify.com/"

  QtObject {
    id: internals
    // Below property triggers the combo box of the relays evaluating the normally closed (NC) or
    // normally opened (NO) circuit
    property string get_normallyClosed_or_normallyOpened_comboBox: "
      var comboBox = document.getElementsByName('859-2-2')[0];
      // Check that we found a target element.
      if (comboBox) {
        // Add event listener to verify that combo change event gets fired.
        comboBox.addEventListener('change', function (e) {
          console.log('Change event detected:', e);
        });

        // Get new option index by flipping the current selected index
        var newIdx = (comboBox.selectedIndex + 1) % 2;
        console.log(comboBox, comboBox.selectedIndex, newIdx);  // debug
        // set the new index
        comboBox.selectedIndex = newIdx;
        // fire change event
        comboBox.dispatchEvent(new Event('change'));
      }
      else {
        console.error('comboBox not found!');
      }
    ";
  }

  Timer {
    id: timer
    interval: 1000; repeat: false
    onTriggered: {
      console.log("Triggered timer with ", view.url);
      view.runJavaScript(internals.get_normallyClosed_or_normallyOpened_comboBox);
    }
  }

  WebEngineView {
    id: view
    anchors.fill: parent
    onUrlChanged: {
      if (url.toString() === root.url)
        timer.running = true
    }
    onCertificateError: function(error) {
      error.ignoreCertificateError();
    }
    Component.onCompleted: view.url = root.url
  }
}
21.11.2019
  • Большое спасибо за пример и за ваше время. Это был отличный и простой способ показать, как работает процесс. Иногда я застреваю на простых вещах. Достаточно было бы console.log вывода! Еще раз большое спасибо! :) 21.11.2019
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...