QT QML 自定义按钮 - 动态改变文本和图像的相对位置

Posted

技术标签:

【中文标题】QT QML 自定义按钮 - 动态改变文本和图像的相对位置【英文标题】:QT QML Custom Button - Dynamically changing the relative position of text and image 【发布时间】:2014-01-15 13:58:33 【问题描述】:

在 QML 上创建的按钮上,图像和文本的相对位置需要动态更改。所以我创建了一个布局属性来改变这个位置。当我用任何位置初始化按钮时,它都可以正常工作,但是当我以编程方式更改位置时,会出现错误。

layout = 0: 图片在文字之上 layout = 1:图片顶部的文字 layout = 2:图片右侧的文字 layout = 3:文字右侧的图片 layout = 4:图片前面的文字

当我将布局从 0 更改为 1 时,反之亦然,没有错误。 当我将布局从 2 更改为 3 时,反之亦然,没有错误。 如果我在任何布局更改之间将布局更改为 5。当我将 Layout 更改为 5 时,所有锚属性都会重置。

很明显,锚属性绑定有问题,但我不知道它是什么。如果有人有有效的代码或可以告诉我有什么问题,我将不胜感激。

代码:

Rectangle 
    Gradient 
        id:myGradient
        GradientStop  position: 0.0; color: neoButton.color 
        GradientStop  position: 1.0; color: Qt.darker(neoButton.color,1.5) 
    
    Gradient 
        id:myDarkyGradient
        GradientStop  position: 0.0; color: Qt.darker(neoButton.color,1.7) 
        GradientStop  position: 1.0; color: Qt.darker(neoButton.color,1.7) 
    
    property string image
    property color fontColor
    property int fontSize:70
    property int layout:2
    property string text:"Button"

    clip: true
    id:neoButton
    width: 300
    height: 160
    x:50
    y:50

    border.color : "black"
    border.width: 1
    radius: 5
    Rectangle
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        implicitWidth:
            if((neoButton.layout==0)||(neoButton.layout==1)||(neoButton.layout==4))
               return Math.max(buttonLabel.implicitWidth, buttonImage.implicitWidth)
            else
                return buttonLabel.implicitWidth+buttonImage.implicitWidth
            
        
        implicitHeight:
            if((neoButton.layout==0)||(neoButton.layout==1))
              return  buttonLabel.implicitHeight + buttonImage.implicitHeight
            else
               return Math.max(buttonLabel.implicitHeight, buttonImage.implicitHeight)
            
        
        color: "blue"
        Image
            id:buttonImage
            anchors.horizontalCenter:
                if((neoButton.layout==0)||(neoButton.layout==1)||(neoButton.layout==4))
                  console.log("Image horizontalCenter:parent.horizontalCenter" )
                    return parent.horizontalCenter
                else
                   console.log("Image horizontalCenter:undefined" )
                    return undefined
                
            
           anchors.verticalCenter: 
               if((neoButton.layout==2)||(neoButton.layout==3)||(neoButton.layout==4))
                 console.log("Image verticalCenter:parent.verticalCenter" )
                   return parent.verticalCenter
               else
                   console.log("Image verticalCenter:undefined" )
                   return undefined
                
           
            source:"file:///D:/QT Projects/build-PutCppAndQmlTogether-Desktop_Qt_5_1_1_MinGW_32bit-Debug/MyTempFiles/Images/B_0_0_0.png"
            anchors.top: 
                if(neoButton.layout == 1)
                    console.log("Image top:buttonLabel.bottom" )
                    return buttonLabel.bottom
                 else if(neoButton.layout == 0)
                    console.log("Image top:parent.top" )
                    return parent.top
                else
                    console.log("Image top:undefined" )
                    return undefined
                 
            
            anchors.left: 
                if(neoButton.layout == 3)                        
                    return buttonLabel.right
                
                else if(neoButton.layout == 2)                       
                    return parent.left
                else                        
                    return undefined
                 
            
        
        Text
            id: buttonLabel
            font.pixelSize:20

            anchors.horizontalCenter:
                if((neoButton.layout==0)||(neoButton.layout==1)||(neoButton.layout==4))                         
                  return  parent.horizontalCenter
                else                        
                    return undefined
                 
            
           anchors.verticalCenter: 
               if((neoButton.layout==2)||(neoButton.layout==3)||(neoButton.layout==4))                      
                   return parent.verticalCenter
               else                       
                   return undefined
                
           
           anchors.top: 
               if(neoButton.layout == 0)                       
                   return buttonImage.bottom
               
               else if(neoButton.layout == 1)                       
                   return parent.top
               else                       
                   return undefined
                
           
           anchors.left: 
               if(neoButton.layout == 2)                       
                   return buttonImage.right
                else if(neoButton.layout == 3)                      
                   return parent.left
               else                       
                   return undefined
                
           
            text: neoButton.text                
        
    

    signal buttonClick()
    onButtonClick: 
        console.log(buttonLabel.text + " clicked" )
        layout=2
    

    MouseArea
        id:buttonMouseArea
        anchors.fill: parent
        onClicked: parent.buttonClick()
        hoverEnabled: true
        onEntered:
            parent.border.width= 2
        
        onCanceled:
            parent.border.width= 1
        
        onExited: 
            parent.border.width= 1                             
        
    
    gradient: buttonMouseArea.pressed ? myDarkyGradient : myGradient

【问题讨论】:

【参考方案1】:

如果再添加一些调试输出,可以观察属性变化的顺序,然后设置一个新的layout

示例 0 -> 2

/* Console log output
'Text Button' clicked: Change layout 0 to 2
Label horizontalCenter: undefined
Label verticalCenter: parent.verticalCenter
Label top: undefined
Label left: buttonImage.right
Image horizontalCenter:undefined
Image verticalCenter:parent.verticalCenter
Image top: undefined
Image left: parent.left
Rectangle implicitWidth: Sum
Rectangle implicitHeight: Max
*/

这意味着最后重新计算外部矩形。因此,所有其他对齐都相对于旧矩形发生。

要重置锚点,我会实现自动生成的函数“onLayoutChanged”:

onLayoutChanged: 
    console.log("Layout changed to new id: " + layout + ". Time to reset alignments using javascript")

    switch(layout) 
    case 0:
        // do stuff
        break;
    case 1:
        // do stuff
        break;
    case 2:
        // do stuff
        break;
    case 3:
        // do stuff
        break;
    case 4:
        // do stuff
        break;
    default:
        console.log("Invalid layout id.")
        break;
    

【讨论】:

谢谢,这比我做的要好得多。但是在初始化按钮时不会调用此方法。最好的方法是什么? 将逻辑导出到新的 JavaScript 函数 setLayout(layoutId) 并从 onLayoutChangedComponent.onCompleted 调用它(参见 qt-project.org/doc/qt-5.0/qtqml/…)。 现在它可以工作了,我只需要在设置新的锚之前清除以前的锚。非常感谢。

以上是关于QT QML 自定义按钮 - 动态改变文本和图像的相对位置的主要内容,如果未能解决你的问题,请参考以下文章

使用 Qt.createQmlObject() 创建自定义 qml 对象实例

Qt5 / PyQt5 : 带有 QML 前端和 Python 后端的自定义 QML 组件

Qt5 和 Qt Quick 2 中的自定义实时绘图

BlackBerry Cascades 中的 QML 字符串

QML程序实现动态切换多语言(ListModel/ListElement中的文本的多语言处理)

QML程序实现动态切换多语言(ListModel/ListElement中的文本的多语言处理)