针对 QML 中的特定组件元素

Posted

技术标签:

【中文标题】针对 QML 中的特定组件元素【英文标题】:Targeting specific component elements in QML 【发布时间】:2018-06-28 17:11:10 【问题描述】:

CSS 让 yhour DOM 中特定按钮/元素的悬停效果变得非常容易。我正在尝试为桌面应用程序创建各种登录页面,但我试图避免为我在 main.qml 中创建的每个对象复制粘贴特定状态。

这是我的 main.qml

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4

Window

    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    NavBar
    
        id: mainNavigation

    

NavButton.qml

Rectangle

    id: navButton
    height: parent.height
    width: parent.width / 3 - 10
    color: "orange"

    MouseArea
    
        state: "unhovered"
        hoverEnabled: true
        height: parent.height
        width: parent.width
        onHoveredChanged:
        
            console.log("hovered")
            if(this.state == "hovered")
            
                parent.state = "unhovered"
            
            else
            
                parent.state = "hovered"
            
        
     // end mouse area

    states:
    [
        State
        
            name: "hovered"
            PropertyChanges
            
                target: navButton
                width: parent.width
                color: "red"

            
        ,
        State
        
            name: "unhovered"
            PropertyChanges
            
                target: navButton
                width: parent.width
                color: "orange"
            
        
    ]

NavBar.qml

import QtQuick 2.0
import QtQuick.Controls 1.4

Row

    id: navigationBar
    height: parent.height / 3
    width: parent.width
    spacing: 15
    anchors.centerIn : parent


    NavButton
    
        id: selectDevice
    

    NavButton
    
        id: deviceConfig
    

    NavButton
    
        id: deviceInfo
    

现在,当我将鼠标悬停在其中一个导航按钮上时,它们三个都会扩大尺寸,而我只将鼠标悬停在其中一个上时会扩大并改变颜色。我希望像 CSS 和 javascript 一样,有一种方法可以定位作为悬停事件主题的元素。

我已经尝试过使用 parent 作为状态的目标,但这似乎不起作用。我已经做了一些寻找解决方案的工作,但我没有看到任何明显的东西可以让我完成这个任务。我看到的唯一选择是将状态添加到我的 navBar 文件中的每个单独的 navButton 。

我真的希望不是这样,因为这将是一个简单问题的非常冗长的解决方案。

我真正需要的是一种仅针对发生事件的元素的方法。

【问题讨论】:

【参考方案1】:

您可以简单地废弃所有这些状态和诸如此类的东西,对于这种微不足道的场景来说,这些状态确实不需要:

Rectangle 
    id: navButton
    height: parent.height
    width: parent.width / 3 - 10
    color:  ma.containsMouse ? "red" : "orange"
    property alias hoverEnabled: ma.hoverEnabled

    MouseArea 
        id: ma
        anchors.fill: parent
    

而且你也为自己节省了一大堆代码。然后只需将hoverEnabled: true 用于您想要悬停的所有按钮。

或者你可以创建一个名为HoverButton.qml的辅助类型,如果你想避免为每个按钮设置它,它只是一个NavButton hoverEnabled: true

我还建议您切换按钮的嵌套顺序:

MouseArea 
    id: navButton
    height: parent.height
    width: parent.width / 3 - 10

    Rectangle 
        anchors.fill: parent
        color: navButton.containsMouse ? "red" : "orange"
    

这避免了使用属性别名的需要,为您节省了一个 id 并允许您直接绑定到鼠标区域处理程序挂钩,如果不使用额外的处理程序和信号重定向信号,您无法在原始代码中执行此操作.

最后,我认为将 QML 看成是 html 是没有意义的,QML 不是 HTML,它有自己的使用范例。

【讨论】:

哇,太棒了。我明白你所说的 QML 有它自己的范式的意思,我并没有把它与 HTML 和 CSS 进行比较,因为我想知道我必须缺少什么才能让它看起来更加困难。我从来没有想过你可以用这种方式来做,因为它与 Javascript 中的标准思维有很大的不同。一般来说,我学会了从事件和事件处理程序的角度来思考,所以这是相当不同的!再次感谢您的解决方案 - 正如我所说的那样,我永远不会想到。 如果可以,我想进一步问一下,如何通过过渡期实现这一点?我可能应该一开始就问这个问题,因为我觉得它改变了人们可能采取的方法,但也许我错了!我的意图是“动画”颜色和大小。我已经看到通过状态和转换完成了这一点,但这给我留下了我原来的问题。 QML 有点像 CSS,它是一种类似 HTML 的标记,但它的整体设计理念是不同的。 IMO 管理层做出了一些错误的决定,即在 Web API 之后对某些 API 进行建模,以吸引 Web 开发人员并增加 QML 的采用,这可能会进一步强化技术相似的想法,但事实并非如此。 QML 与 HTML 非常不同,期望相同的工作流程会适得其反。至于动画——只要查一下,有几种方法可以做到。最简单的一种是在属性上安装Behavior,它会自动为更改设置动画。

以上是关于针对 QML 中的特定组件元素的主要内容,如果未能解决你的问题,请参考以下文章

如何从QML中的GridView或ListView获取实例化的委托组件

QT开发(五十四)———QML组件

qml 桌面组件缩放

所有自定义 QML 组件都应该将“Item”作为其根元素吗?

使用Qt Quick 设计器 十五

QML 可重用组件