【问题标题】:Qt5-QML: How to handle a combobox in QML via JavaScriptQt5-QML:如何通过 JavaScript 处理 QML 中的组合框
【发布时间】:2020-03-16 18:48:51
【问题描述】:

我正在使用第三方路由器通过 wi-fi 访问我自己的机器人。 我编写了一个小应用程序,它可以自动登录到路由器,通过路由器界面的tab 导航,所有这些都在QML 应用程序中使用JavaScript。 我遇到的一个小问题是我必须触发一个继电器来打开/关闭机器人,并且在路由器 GUI 内部我需要触发一个combobox,如下面的打印屏幕所示。点击I/O标签后,路由器页面地址为https://123.456.789.123:7878/admin/ACEmanagerX.html#

对应的html也如下图所示:

编辑

现在,为了重现我遇到的问题,我部署了一个非常小的网站https://comboboxtest.netlify.com/,它只带有一个我试图触发的同名和相同选择的组合框。

问题是我找不到简单的方法来触发继电器的开启或关闭。

预期行为将是:如果是 OFF(值 0),则将其设置为 ON(值 1,即 Drive Active Low),反之亦然。

如果您复制/粘贴下面的代码并运行它,它将自动打开网站,但不幸的是,它不会将组合框从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) 在经过this post 之后,我发现给http 请求启动的时间非常重要。这就是为什么我在进入 I/O 标签后添加了interval: 20000。但是,这没有用,也没有触发组合框。

2) 我使用this source 帮助我弄清楚如何通过JavaScript 触发组合框,这正是我应用的,但我没有看到组合框中的任何值发生变化.

3) 我发现this post 与我正在做的非常接近,不同的是这里还使用了Button 来触发组合框。但就我而言,我没有按钮。

我知道我已经接近让它工作了,但是我缺少一些东西。感谢您为解决问题而阐明此问题

【问题讨论】:

  • 一些要点...首先,您将多个不相关的问题混合到一个问题/问题中,这样单独处理会更容易。第二,你的 MRE 不是一个,因为有明显的错误和缺失的部分,而且没有办法在不编写自定义 HTML 页面的情况下重新创建它。很难说什么是真正的错误,或者只是你删掉的东西。我看到了一堆可能的问题,其中最明显的是document.getElementById('859-2-2') 将不起作用,因为该 ID 没有元素——即元素 name。使用document.getElementsByName('859-2-2')[0]
  • 请参阅 stackoverflow.com/questions/51810358/… 以从 QML 中以编程方式退出应用程序。
  • @MaximPaperno,感谢您阅读问题。我通过JavaScript 更新了关于如何处理组合框的问题,并将为第二部分编写一个单独的问题。
  • @MaximPaperno,我尝试了修改document.getElementsByName('859-2-2')[0];,但我仍然看到触发组合框没有任何变化。 JavaScript 函数中我没有看到什么?
  • @MaximPaperno,按照您的建议,我这样做是为了让问题变得更加简单:我创建并部署了一个小型网站https://comboboxtest.netlify.com/,并修改了我发布的代码。有部分 EDITS 我认为现在更简单。现在,如果您完全运行该代码,它将自动打开网站,但不幸的是,它仍然不会触发组合框。也有可能inspect the element 并查看html 页面

标签: javascript qt c++11 qml qt5


【解决方案1】:

我为你想出了一个可行的例子。这里真的没有什么棘手的,只是精确的语法、学习 JavaScript,以及特别是注意 Qt 在运行时产生的警告消息。我对后者的压力再怎么强调也不为过——如果你看不到控制台输出,那么它甚至不值得测试。即使是最新清理的 MRE 也会生成控制台警告,这些警告很容易解决,之后真正的问题变得更加明显。

有两个主要变化。首先测试

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

从来没有true。使用console.log() 非常基本且易于确定。将 URL 与字符串进行比较的好方法是使用 url.toString()

其他重大变化是在 Web 视图/浏览器中运行的脚本。我试着注释一下。希望我正确理解了目的——将组合框中的选择切换到与当前选择相反的位置,然后触发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
  }
}

【讨论】:

  • 非常感谢您提供的示例和您的时间。这是展示该过程如何运作的一种伟大而简单的方式。有时我会被简单的事情困住。 console.log 输出就足够了!再一次非常感谢你! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
相关资源
最近更新 更多