QML Changing style of TextField's menu - qt

I would like to customize style of my application and I'm stuck on the style of TextField pop-up menu.
TextField.style allows to customize the look of TextField but it doesn't contain the style of the menu. According to documentation there is a property menu containing the Menu so I tried something like this:
TextField {
menu.style: MenuStyle {
//...
}
}
Code above complains that property style is non-existent so it's not exactly Menu, it's Component used to create the menu and I don't know if there is a way to get through it to the actual Menu. Documentation only mentions that TextField.menu can be set to null to disable it completely and doesn't provide other use cases.
So is there a way to get to the menu of TextField and change its style?

Well, you should post all relevant code here. Anyway, you cannot define the TextField menu and its style separately. See the example below to customize Menu style and adding it to the TextField inline:
TextField {
text: "text here"
anchors.centerIn: parent
menu: Menu {
style: MenuStyle {
frame: Rectangle {
color: "green"
border.color: "purple"
}
itemDelegate {
background: Rectangle {
color: "yellow"
}
label: Text {
color: styleData.selected ? "red" : "blue"
text: styleData.text
}
}
}
MenuItem { text: "Cut" }
MenuItem { text: "Copy" }
}
}
See this page for complete list of MenuStyle properties.

Related

Change ListView's current index background color and not override other "states"

My Qt Quick Control 2 app is using Material Dark Theme. I would like to change background color of selected item in ListView. I know that I can do this in item delegate:
SwipeDelegate {
id: delegate
checkable: true
spacing: 0
width: parent.width
background: Rectangle {
color: index===currentIndex ? "red" : "transparent"
}
But with change above I'm losing defaults padding etc and also Material's radial animation on press and hold state is missing too. Is it possible to just change color only of selected item and keep original behavior for other states of item? Seems that I must reimplement missing things by my self
Maybe you should consider to implement highlight. The following worked for me:
ListView {
// ... Your stuff ...
highlight: Rectangle { color: "lightsteelblue"; }
focus: true
}

Correct way to change color of a combobox in QML

What is the correct way to change the color in a combobox?
I know that i can do this:
ComboBox {
background: Rectangle {
color:"blue"
}
}
and it turns like this:
but then i lose the focus border (at least it appears when i do tab to go from one control to another) that is normal to appear in the combobox:
What is the solution?
As pointed by folibis we can find the answer to do that in the source
i did the following:
ComboBox {
id:comboBoxCustom
background: Rectangle {
color:"white"
border.width: parent && parent.activeFocus ? 2 : 1
border.color: parent && parent.activeFocus ? comboBoxCustom.palette.highlight : comboBoxCustom.palette.button
}
}

How to make qml tab order navigation?

How to make tab order navigation in QML
For example I have such code:
TextInput { id: one }
TextInput { id: two }
TextInput { id: three }
And I need on pressing tab from focus on "one" move to "three", haven't found that in official documentation.
TextInput {
id: one
KeyNavigation.tab: three
}
Key navigation in QML is documented at this page and provide some example at:
http://qt-project.org/doc/qt-4.8/qml-keynavigation.html

Change text color for QML controls

I am using some QML controls like GroupBox and CheckBox which have text associated with them. The default color of the text is black. However, I have these items on a dark background and would prefer using white for the text color. These items don't have a color property so I'm not sure what to do.
CheckBox {
text: "Check Me"
}
I had the same problem with GroupBox so I wanted to post an answer for future reference.
The problem can easily be fixed using HTML formatting. For instance to change the color:
GroupBox{
title: "<font color=\"white\">my title</font>"
}
Size and other formatting parameters can be changed the same way.
Have you tried setting it as an entire sub-element of the checkbox?
CheckBox {
Text {
text: "Check Me"
color: "red"
}
}
You need to use the style property to redefine the Component to use for the label based on the CheckBoxStyle
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
Rectangle {
color: "black"
CheckBox {
style: CheckBoxStyle {
label: Text {
color: "white"
text: "check Me"
}
}
}
}
When using CheckBoxStyle you might have to redefine the whole component and not just the label property.

How to define a "template" with child placeholders in QML?

I really like QML. I like how I can define components (comparable to classes) and their properties, and instantiate them from somewhere else (comparable to objects).
I can define, let's say, a button, having some look and feel, and a label text on it. This could be done, for example, using this component definition (Button.qml):
Item {
id: button
property string label
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Text {
anchors.centerIn: parent
font.pixelSize: 20
text: button.label
color: "white"
}
}
}
and instanciated in this main file (main.qml):
Rectangle {
width: 300
height: 200
Button {
anchors.centerIn: parent
anchors.margins: 50
label: "Hello button!"
}
}
But I see the following restriction: I can only define a button template with some properties, not with some placeholder. All children defined in the instance will be direct children, at least per default, and I want to change this behavior.
Let's say I want to place an item (let's say an image, but I don't want to tell the definition of Button that it will be an image) in the button. I imagine something like this:
Item {
id: button
property Item contents <-- the client can set the placeholder content here
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
Component.onCompleted: {
// move the contents into the placeholder...
}
}
How can I achieve this? I don't know if using Component.onCompleted is the correct way. Note that, however, that in my case the contents will never change afterwards (at least in my current design of the application...).
Also, I want anchoring to work within the placeholder. For example, if I define the contents to be a Text element, being centered in its parent (which will first be the template itself). Then my code moves this Text instance into the placeholder and the parent anchors should then be those of the placeholder item, not the template item.
I found a much nicer answer to this question, suggested in a presentation of the Qt Developer Days 2011 "Qt Quick Best Practices and Design Patterns".
They use default property alias ... to alias the child items to any property of any item. If you don't want to alias the children but give the alias property a name, just remove default. (Literal children are per QML definition the value of the default property.)
Item {
id: button
default property alias contents: placeholder.children
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
}
Necro answering in case someone else end up here as I did.
In Qt5 somewhere along the line the default property became "data" and not "children".
This makes it possible to add other object types than "Item".
e.g. Connections can be added as well (to answer my own question above)
So in Qt5 you should do:
Item {
id: button
default property alias contents: placeholder.data
anchors.fill: parent
Rectangle {
anchors.fill: parent
radius: 10
color: "gray"
Item {
id: placeholder <-- where the placeholder should be inserted
}
}
}
Note the:
placeholder.data instead of placeholder.children
Also please note that you don't have to use the alias name contents - this can be anything you like. An example:
Item {
id: button
default property alias foo: placeholder.data
...
}
Actually, the correct answer from what I've heard is to use a QML Loader to accomplish what you want.
[that being said; I haven't actually tried it yet but it's on my near-term to-try list and looks fairly straight forward]
Also, search stackoverflow for other "QML Loader" questions as there are a number that will help you get started.
You can move the item(s) (if you want to support multiple items within the placeholder) using this piece of code:
property list<Item> contents
Component.onCompleted: {
var contentItems = [];
for(var i = 0; i < contents.length; ++i)
contentItems.push(contents[i]);
placeholder.children = contentItems;
}
Note that you do not have to provide a list of Items for the contents property, as single values will be accepted by the QML engine also for list properties.
In short (to show the idea):
import QtQuick 1.1
Item {
width: 200
height: 100
//<-- the client can set the placeholder content here
property Item contents: Rectangle {
anchors.fill: parent
anchors.margins: 25
color: "red"
}
Rectangle {
id: container
anchors.fill: parent
radius: 10
color: "gray"
//<-- where the placeholder should be inserted
}
Component.onCompleted: {
contents.parent = container
}
}
Somewhat longer version (supporting contents reassignment):
import QtQuick 1.1
Item {
width: 200
height: 100
//<-- the client can set the placeholder content here
property Item contents: Rectangle {
//anchors can be "presupplied", or set within the insertion code
//anchors.fill: parent
//anchors.margins: 25
color: "red"
}
Rectangle {
id: container
anchors.fill: parent
radius: 10
color: "gray"
//<-- where the placeholder should be inserted
//Item {
// id: placeholder
//}
}
//"__" means private by QML convention
function __insertContents() {
// move the contents into the placeholder...
contents.parent = container
contents.anchors.fill = container
contents.anchors.margins = 25
}
onContentsChanged: {
if (contents !== null)
__insertContents()
}
Component.onCompleted: {
__insertContents()
}
}
Hope this helps :)

Resources