Conditional alignment in a delegate based on text width?



  • I have a listview that works great, and when a name that is very long is displayed, it is clipped properly.

    My problem is that if the text fits inside the width of the text control I would like it to be horizontally centered. If the text is too long and will be clipped, I want it aligned to the left so that you can read the start of the 'name' and the excessive portion is clipped only on the right.

    Text {
    	id: textName
    	x: 18
    	y: 6
    	width: 392
    	height: 28
    	color: "#ffffff"
    	text: ""
    	font.bold: true
    	font.pixelSize: 22
    	style: Text.Outline
    	clip: true
    	wrapMode: Text.NoWrap
    	verticalAlignment: Text.AlignVCenter				
    	horizontalAlignment: ( text.paintedWidth > width ) ? Text.AlignLeft : Text.AlignHCenter
    }
    

    This text declaration is inside of my delegate declaration like this:

    delegate:  Rectangle {
        ...some values
        Text {
            ...the text declaration shown above.
        }
    }
    

    I was expecting the conditional I placed in the horizontalAlignment property to get evaluated at least everytime the value of Text.text changed. Unfortunately, it never evaluates as anything other than false (and therefore always horizontally centering the text.)

    Event if I set the default value of text to some really long string, it acts as if text.paintedWidth is always less than the width.

    If I force the evaluation to be 'true' I get left justified text, e.g.:

    horizontalAlignment: ( true ) ? Text.AlignLeft : Text.AlignHCenter
    

    Is there something I'm missing?

    Thanks :)



  • I was misusing things... Here's how to do this (at least how I just found how to do this - I am interested in other solutions as well)

    Text {
    	id: textName
    	x: 18
    	y: nTextStartingY
    	width: 392
    	height: 28
    	color: "#ffffff"
    	text: name
    	font.bold: true
    	font.pixelSize: 22
    	style: Text.Outline
    	clip: true
    	wrapMode: Text.NoWrap
    	verticalAlignment: Text.AlignVCenter
    
    	FontMetrics {
    		id: textNameFontMetrics
    		font: textName.font
    	}
    
    	horizontalAlignment: ( textNameFontMetrics.boundingRect( textName.text ).width >= textName.width ) ? Text.AlignLeft : Text.AlignHCenter
    }
    

    Works nicely for me.



  • You can simply compare the text implicitWidth to its parent's width which serves as its holder.

    Item {
         x: 18
         y: nTextStartingY
         width: 392
         height: 28
    
        Text  {
            anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
            horizontalAlignment: implicitWidth >= parent.width ? Text.AlignLeft : Text.AlignHCenter
         }
      }
    

    Hope this helps.



  • I will give that a try, thanks! It would be much less brute force than my current solution.



  • @VRHans I just modified my answer because i noticed that you have a specific width set on the Text component. As you noticed, I created an Item which serves as the holder/container and anchored the Text to it.


  • Moderators

    Hi! You can also use contentWidth:

    horizontalAlignment: ( contentWidth > width ) ? Text.AlignLeft : Text.AlignHCenter
    


  • @Wieland - For some reason I can't mark your reply as the answer/solution, the option isn't available.


  • Moderators

    @VRHans Yes, the new forum (it's actually not that new anymore :)) doesn't support this. Voting good answer up with the thump up button is the way to go.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.